Webpacker in Development

In development, we mostly worry about three things: writing our code, getting our code onto the page, and being able to recompile the code quickly and easily.

Writing Code Using Webpacker

Somewhat uncharacteristically for Rails, Webpacker does not suggest any structure for our code beyond having the entry point be in app/packs/entrypoints. The important feature is that we can import files relative to either app/packs (for our own code) or node_modules (for third-party code).

That said, here are some suggestions:

  • Keep as little code as possible in your actual entry point, it should mostly be imports.

  • Where possible, having multiple modular small pack files is probably better than having a single one (There’s a webpack optimization that makes this optimal from a download standpoint.

  • If you import a directory, rather than a file, the module system will automatically import the index.js (or index.ts) file in that directory. We’ve already seen this in our boilerplate code: the pack imports controllers and controllers/index.js handles the autoload of controller modules. You can use this to modularize your imports somewhat and make it easy to share common imports across pack files.

  • Your framework of choice may have some community standards for how code is structured. If so, you should follow them.

  • You should not put anything other than entry point files in the entrypoints directory, and you should not create any subdirectories there either, since you will not be using those subdirectories for regular source code.

  • Avoid creating a top-level app/packs/src directory on the ground that anything in the app/packs directory is a source of some kind or other. Try to be more specific about top level names. You can, though, separate out CSS into app/packs/stylesheets. You can, though, separate out CSS into app/packs/stylesheets.

Using Packs

To use a pack in our Rails code, we use the helpers javascript_pack_tag or stylesheet_pack_tag. These use webpack “chunks” by default. In webpack, a chunk is a way to extract common dependencies so that if we are importing multiple packs, shared dependencies are only downloaded to the browser once.

Both of the helpers work the same way. The arguments are a list of pack names and an optional set of options. The helper creates a script tag (for JavaScript) or a link tag (for CSS) for each pack name in the list.

Both methods simply defer to the existing Rails helpers javascript_include_tag and `stylesheet_include_tag, and any options are passed right through. In practice, though, most of the options for the existing Rails helpers have to do with modifying the eventual URL and aren’t relevant to packs.

There’s a bit of tension between the classic Rails structure of just putting the javascript_include_tag in the header for all pages and what is probably a more webpack-idiomatic structure of using many small packs and only loading the ones we need for each page.

Therefore, if your setup is at all complicated, we recommend using the Rails content_for feature to customize the header on a per-page basis.

To do this, in the HTML header where we might otherwise have the call to javascript_pack_tag, try this instead:

<%= yield(:packs) %>

Then in any page that uses packs, do something like this:

<% content_for :packs do %>
  <%= javascript_pack_tag(:application) %>
<% end %>

The yield/content_for construct allowsus to customize the webpack output on a page-by-page basis and has the side benefit of making the available JavaScript visible on the individual page itself, which can make it a little easier to figure out what’s going on.

Get hands-on with 1200+ tech skills courses.