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 to learn more about using webpack with Rails.

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.

Discuss it on Twitter · Published on Apr 11, 2020

Need help with Webpack on Rails?

My name is Ross Kaffenberger.

Webpacker now ships by default in Rails 6 but there's no need to stress. I'm putting together a course to help you master Webpack on Rails.

I teach full stack web developers about frontend tools and performance, especially at the intersection of JavaScript and Ruby on Rails.

Subscribe to stay in the loop.

    More posts

    How to debug webpack on Rails

    Understanding your Rails webpack configuration and build output can be a little confusing, especially if you're new to either Rails or webpack. This post contains a few tips for debugging your Webpacker setup, some specific to Rails Webpacker, some generally applicable to webpack.

    How to customize webpack in Rails apps

    Configuring webpack is precisely the main job of Webpacker's NPM package, @rails/webpacker. This post provides an overview of how to customize its default settings for your Rails application.

    jQuery plugins in webpack without jQuery

    Upgrading jQuery plugins to work with webpack is a common source of confusion. If you're lucky, you may find they can work in either context such that you might not need jQuery at all.

    Photo by Adi Goldstein on Unsplash