Understanding webpacker.yml
An unofficial guide to Rails Webpacker YAML configuration
Though Webpacker adds a layer of "convention over configuration" in regards to webpack integration with Rails, the need for configuration remains. In this post, I'll describe the role of the webpacker.yml
file for Webpacker configuration.
One of Webpacker's primary roles is helping Rails communicate with webpack.
Here are some things both Rails and webpack need to know:
Where are the source files located?
What file types should be bundled?
What's the destination for the bundle files?
Should CSS be inserted dynamically via JavaScript or output as a separate file?
What port should the webpack-dev-server listen on in development?
That's where webpacker.yml
comes in.
This file is read both Ruby code supplied by the Webpacker gem in the Rails server process and the JavaScript process that generates the webpack configuration via the @rails/webpacker
NPM package. It supports a number of YAML entries which I'll describe in more detail in the reference guide.
Subscribe to my newsletter, Joy of Rails, to get notified about new content.
Creating and updating
Webpacker expects to find this file at config/webpacker.yml
within your Rails project. It is installed via the following command, provided by the Webpacker gem.
rails webpacker:install
The installer also generates environment-specific JavaScript files in config/webpack/
.
config
│ ...
├── webpack
│ ├── development.js
│ ├── environment.js
│ ├── production.js
│ └── test.js
└── webpacker.yml
When upgrading the Webpacker gem, it's prudent to re-run the installer command to bring in new changes from the default webpacker.yml
template. Differences will have to be merged intentionally to avoid losing project-specific customizations.
Limitations
The webpacker.yml
config file does not work with ERB as is typical with other Rails YAML config files, since the file must also be read in JavaScript. This may come as a surprise as indicated by recent issues, e.g. #1615, #956.
One possible workaround is to use one of the supported ENV var overrides. It may also be an option to manipulate the JavaScript config in one of the config/webpack
JavaScript files—look for a future post on the subject.
Reference guide
Following is reference guide for supported Webpacker configuration options as of Webpacker version >= 4
.
source_path
The primary subdirectory within your Rails application where your webpack source code is located. Your source_entry_path
directory should be located here. You can add to the list of source paths using additional_paths
. Change this directory to something like app/frontend
if you use webpack for non-JavaScript assets like CSS, images, fonts, etc.
source_path: app/javascript
source_entry_path
The subdirectory within source_path
where your webpack entry point files are located. For example, given a source_path
of app/javascript
, a source_entry_path
of packs
, and an entry point named application.js
, the path to this file from Rails root should be app/javascript/packs/application.js
.
source_entry_path: packs
!!!Warning!!! Only use this directory for webpack entry points! A common webpacker mistake is placing too many files in this directory.
additional_paths
This option expects an array of subdirectories where webpack should resolve modules. Given additional_paths
of ["app/assets/images"]
, webpack will lookup modules in your source_path
, node_modules
, and app/assets/images
. When watching for file changes in development, webpack watched paths would include the source_path
and additional_paths
. The additional_paths
key replaces the resolved_paths
key in earlier versions of Webpacker, so this is a key you'll want to rename when upgrading to Webpacker 5+.
additional_paths:
- app/assets/images
public_root_path
The primary destination within your Rail application where your compiled webpack assets are output. For most applications this should be public
, i.e., corresponding to Rails.public_path
. When configuring webpacker for a Rails engine, this value could be relative to the engine root, such as ../public
.
public_root_path: public
public_output_path
The subdirectory destination within the public_output_path
where your compiled webpack assets are output. For example, given a public_root_path
of public
and a public_output_path
of packs
, the webpack manifest file, which maps canonical asset names to their fingerprinted output filenames, would be located at public/packs/manifest.json
within your Rails application.
public_output_path: packs
cache_path
The subdirectory where webpack, webpacker, babel, etc. will write cache files to enhance recompilation times. For example, given a cache_path
of tmp/cache/webpacker
, webpacker will write a SHA1 digest on each compilation of your source files in development to a file tmp/cache/webpacker/last-compilation-digest-development
.
cache_path: tmp/cache/webpacker
webpack_compile_output
Set to true
to print webpack output do STDOUT or false
to silence. Unless you're extremely confident in what you're doing, the only correct value for this setting is true
.
webpack_compile_output: true
cache_manifest
The webpack manifest.json
is one of the crucial files in output webpacker asset compilation. It provides a mapping of canonical asset names to their fingerprinted filenames, e.g. "application.js": "/packs/js/application-abcdefg12345.js"
. Rails uses the manifest to lookup the location of assets on disk. The cache_manifest
setting simply tells Rails whether we want to maintain the parsed manifest in Ruby memory. Set this to false
in development
where you'll be making frequent changes to your source code; true
in all other environments.
cache_manifest: true
extract_css
Given a webpack bundle application.js
that imports CSS, webpacker can be configured to emit the compiled CSS in one of two ways: 1) extracted as a separate file called application.css
as you might expect from the Rails asset pipeline, or 2) as a JavaScript module that webpack will insert as CSS into the page dynamically when loaded in the browser. extract_css: false
is helpful for development; most applications will want to set extract_css: true
in production.
extract_css: true
Important With extract_css: true
, you must use stylesheet_pack_tag
, i.e, <%= stylesheet_pack_tag "application" %>
, in your Rails view. This can be easy to miss in deployed environments after using extract_css: false
for local development.
static_assets_extensions
Provide a list of file extensions, such as .jpeg
, .png
, .woff
, that webpack should emit as separate files, i.e, import "../my-image.jpg"
will result in webpack emitting a file of that name instead of loading it in memory as a JavaScript module.
static_file_extensions:
- .jpg
- .jpeg
# ...
extensions
Provide a list of file extensions that webpack will recognize when searching for imported files to add to the dependency graph.
extensions:
- .js
- .sass
- .scss
- .jsx
- .vue
compile
Set this to true
only when you want Rails to execute a shell command to compile webpack dynamically when attempting to serve a webpack asset or bundle. Set to false
when webpack assets should be precompiled, as in production
or when instead using the webpack-dev-server
to handle webpack asset requests, as in development
.
compile: false
dev_server
This config contains a set of key-value pairs that correspond to a subset of the webpack-dev-server
configuration outlined in the webpack docs.
Rails only needs to know the host
, port
, https
values to proxy requests to the webpack-dev-server
in development
. Other dev_server
config values may be set in either webpacker.yml
or in the webpack config exported from config/webpack/development.js
. Make sure at least the following values are set in webpacker.yml
:
development:
# ...
dev_server:
https: false
host: localhost
port: 3035
public: localhost:3035
# ..
To enable auto-recompile when source files are changed:
development:
# ...
dev_server:
# ...
inline: true
# ...
To enable hot-module replacement:
development:
# ...
extract_css: false # to allow HMR for CSS
dev_server:
# ...
inline: true
hmr: true
# ...
Refer to the Webpacker docs and webpack docs for more info.
ENV var overrides
Some Rails configuration can be overriden via ENV vars. This is especially helpful to workaround certain limitations. Many of the dev_server
options can be specified in upcase with the prefix WEBPACKER_DEV_SERVER_
, as illustrated below:
WEBPACKER_DEV_SERVER_HOST=localhost \
WEBPACKER_DEV_SERVER_PORT=8765 \
WEBPACKER_DEV_SERVER_PUBLIC=localhost:8765 \
./bin/webpack-dev-server
Other supported Webpacker ENV vars include:
WEBPACKER_NODE_MODULES_BIN_PATH
WEBPACKER_RELATIVE_URL_ROOT
WEBPACKER_ASSET_HOST
Feedback
Did you find this guide useful? Please share it.
Just like with the official Rails guides, you're encouraged to help improve the quality of this one. Please contribute if you see any typos or factual errors.