In the previous article, we saw what Webpacker is and how Rails 6 has integrated it. In this article, we will understand how to use the packs.
A new Rails 6 app creates following files under
The packs directory contains the entry points for webpack to start the compiling process. The content of this file in a new Rails 6 app are as follows.
require("@rails/ujs").start() require("turbolinks").start() require("@rails/activestorage").start() require("channels")
The entry points are analogues to the
app/assets/application.jsfile generated by asset pipeline.
require statement here is not same as the require directive from the asset pipeline. This
require statement can require the NPM packages as well as local modules from our code. For eg. in this case, the first three lines above require three NPM packages - Rails UJS, Turbolinks and Active Storage whereas the last line requires
Webpack has a convention for looking for
index.jsfile under the directory name we are trying to require.
Main difference between the way requiring code between Webpacker and asset pipeline is that we don't use the directives in Webpacker packs. We just directly call
import with the package names or directory names.
Keep pack files minimal and import the actual code in it.
So for a React project, we will just add our base component to the DOM in the pack file and manage rest of the components under
packs directory is special and is treated as entry points by Webpacker. Rest is up to you. I prefer adding a
components directory for all the React components. My application has
application pack as the default pack and
admin pack which has code only related to the admin users.
In the Sprockets world, we have to add every custom file that we want Rails to precompile, in the asset precompile list.
Rails.application.config.assets.precompile += %w[admin.js]
But because the whole
packs directory is considered as entry points by Webpacker, we don't have to add any of the custom packs to the precompile list. It just works!
In general, I will say that we should treat the
▶ ./bin/webpack-dev-server ℹ ｢wds｣: Project is running at http://localhost:3035/ ℹ ｢wds｣: webpack output is served from /packs/ ℹ ｢wds｣: Content not from webpack is served from /Users/prathamesh/Projects/scratch/better_hn/public/packs ℹ ｢wds｣: 404s will fallback to /index.html ℹ ｢wdm｣: Hash: 5387bbdba96d7150c792 Version: webpack 4.39.2 Time: 2753ms Built at: 09/24/2019 12:23:20 AM Asset Size Chunks Chunk Names js/admin-67dd60bc5c69e9e06cc3.js 385 KiB admin [emitted] admin js/admin-67dd60bc5c69e9e06cc3.js.map 434 KiB admin [emitted] admin js/application-d351b587b51ad82444e4.js 505 KiB application [emitted] application js/application-d351b587b51ad82444e4.js.map 569 KiB application [emitted] application js/login-1c7b2341998332589ec0.js 385 KiB login [emitted] login js/login-1c7b2341998332589ec0.js.map 434 KiB login [emitted] login manifest.json 958 bytes [emitted]
Apart from generating the fingerprinted files and source map files, it also generates a
manifest.json which lists information about all the files generated by the compilation process. Rails uses this file to convert references to the assets in the
js/admin-67dd60bc5c69e9e06cc3.js. A sample
manifest.json looks like this.
Now that we have the packs ready, we will use them as per our requirements in the layout files. In my case, the
login pack is only used in
login layout and is separate from
application pack which is used once the user is logged in. For
admin layout, apart from
application pack, a separate
admin pack is used. We can use any of the packs by including it in the layout file.
So to summarize:
- Keep pack files minimal and just import the required code from other files.
- Only pack files must go in
- Keep an eye on the output of Webpack to monitor the bundle size.
- Organize pack files as per your requirements and manage the packs depending on the features they will serve.
If you are interested in knowing more about Webpacker and Rails 6, be with me on the Road to Rails 6.