What is Webpacker?
The goal of Webpack, or any front-end build system, is to allow you to write your front-end code in a way that is convenient for developers and then package that code in a way that is convenient for browsers.
As of Rails 6, Rails started to bundle and wrap Webpack inside the Rails applications. This is done through Webpacker.
Webpacker related files
The Webpacker installation process calls the
yarn package manager, then
package.json file with a basic set of packages listed, and uses Yarn
to install these dependencies.
Along with that the following local files are created by Webpacker:
|Webpacker Configuration||config/webpacker.yml||Configure the Webpacker gem|
|PostCSS Configuration||postcss.config.js||Configuration for the PostCSS CSS Post-Processor|
|Browserlist||.browserslistrc||Browserlist manages target browsers configuration|
There is a
This is how that directory would look like:
1 . 2 ├── channels 3 │ ├── consumer.js 4 │ └── index.js 5 ├── packs 6 │ └── application.js 7 ├── src 8 └── stylesheets 9 └── application.scss
channels directory is generated by Action Cable component of Rails. It's
not that significant for us at the moment.
src directories are usually created by us, manually.
The packs directory
Typically, the file in the
packs directory will be a manifest that mostly
It is important to note that only the Webpack entry files should be placed in
Webpack will create a separate dependency graph for each entry point, so a large number of packs will increase compilation overhead.
If you want to change the default
packs directory path, you can adjust the
packs) in the
Within source files,
import statements are resolved relative to the file doing
import Bar from "./foo" finds a
foo.js file in the same
directory as the current file, while
import Bar from "../src/foo" finds a file
in a sibling directory named
Difference between Webpacker and Sprockets
In particular, code can be added to Sprockets via a Ruby gem.
For transitioning from Sprockets to Webpacker, we can make use of the following tools to achieve tasks:
|Link to an image||image_url||image_pack_tag|
|Link to an asset||asset_url||asset_pack_tag|
|Require a script||//= require||import or require|
Using CSS with Webpacker
Out of the box, Webpacker supports CSS and SCSS using the PostCSS processor.
So if your CSS top-level manifest is in
This tells Webpack to include your CSS file in the download.
To actually load it in the page, include
<%= stylesheet_pack_tag "application" %> in the view, where the
is the same pack name that you were using.
Significance of stylesheet pack tag
We had replaced the
stylesheet_pack_tag in the
application initialization chapter.
The reason is that in
production environment, webpacker by default sets
The way we tell Webpack which files to load is by using
statements. This includes CSS files, images, and everything else.
When we do
import '../stylesheets/application.scss', we're telling Webpack to
application.scss in the build.
How that file compilation is handled will depend upon how our loaders (css-loader, sass-loader, file-loader, etc) are configured.
When we do
<%= stylesheet_pack_tag 'application' %>, that's a run-time
inclusion from Rails, that has nothing to do with whether Webpack has built the
stylesheets or not.
All that line is doing is saying "if you have a pack named
include it here".
If Webpack doesn't build a separate pack of CSS, then this statement won't have anything to load, because no stylesheets were compiled.
Handling Webpacker config for each environment
Webpacker has three environments by default
You can add additional environment configurations in the
and set different defaults for each environment.
Webpacker will also load the file
additional environment setup.
Webpacker during deployment
Webpacker adds a
webpacker:compile task to the
assets:precompile rake task,
so that any existing deploy pipeline that was using
The compile task will compile the packs and place them in
There might be times where we have to debug issues with asset compilation as it's done in production.
We can run the following command to simulate such a compilation locally:
1SECRET_KEY_BASE=`cat config/master.key.sample` RAILS_ENV=production RAILS_SERVE_STATIC_FILES=off bundle exec rails assets:precompile
Webpacker module and version issues
v16.4.2 doesn’t support lower versions of the
node-sass package. We
need at least
But sometimes older
@rails/webpacker package comes bundled with lower versions
Another issue is that the npm
webpacker module's version is incremented very
slowly and is very prone to breaking changes once released.
That's why we stick onto a specific Webpacker version in our application.
While creating the new Rails application if the
installed is not version
5.4.0 then please update the version manually to
You can check default installed Webpacker version by running:
1yarn why @rails/webpacker
Downside of not running Webpack development server during development
When you don't have a Webpack development server running, then while trying to
load the pack assets using Webpacker helper methods like
image_tag, Rails will compile your entire assets on demand rather than
This can be noticed when conditionally rendering CSS with respect to the React
component's state using the
classnames library. In such a case, Webpack will
boot from scratch and re-compile. It can make reloading the page extremely slow.
For this reason it is recommended to use a development server during
Advantages of running Webpack development server during development
Thus reloading after each change will be really slow and time consuming if you are not running Webpack development server. The reason is that by default Webpacker, tries to compile assets from scratch with each request.
Reloading manually before the development server has finished re-compiling, will only reload the same old assets. After compilation is done the browser window running your application will automatically try to fetch the latest assets.
Another benefit of running a Webpack development server along with the Rails server is that it makes catching errors specific to the backend and frontend easier.
When we don't run a Webpack development server, any errors regarding compilation of static assets are logged to the standard Rails log. This is really hard to debug since it's only a single terminal window showing all the errors.
Whereas, upon running a Webpack development server, all compilation errors or
changes in static assets are reflected in only the terminal running the
This will make debugging easier since the errors specific to the frontend side will be logged in the terminal running Webpack development server and the errors specific to Rails side will be logged in the terminal running Rails server.