Webpacker 5.0 released
Webpacker 5.0.1 was released yesterday. The previous release of Webpacker happened in December 2019 which was version 4.2.2. As 5.0 is a major version bump, I decided to see what are the changes from the 4.x series and the 5.x series.
Minimum node version
Minimum node version for Webpacker is now updated to 10.13.0
from 8.16.0
. This means that to use Webpacker, we have to use Node 10.13.0
or above. Node 8 is no longer maintained so this change changes the minimum node version to the next active node version which is 10.x.
How does it affect us?
On Heroku, Node version 10.x, 11.x and 12.x are supported so we don't have to change anything.
If we are using Node 8 locally or on your deployment server, we will see an error when trying to use Webpacker 5.
➜ yank-notifier git:(master) ✗ bundle exec rake assets:precompile
yarn install v1.22.4
[1/4] 🔍 Resolving packages...
success Already up-to-date.
✨ Done in 0.63s.
I, [2020-03-25T20:52:13.580560 #12181] INFO -- : Writing /Users/prathamesh/Projects/sources/yank-notifier/public/assets/manifest-cadda289ef9c70eaa0879a36e6263cb33f7523a16b3ef862e0b8609cdc2bdab1.js
....
Webpacker requires Node.js ">=10.13.0" and you are using v8.17.0
Please upgrade Node.js https://nodejs.org/en/download/
Exiting!
Minimum Rails version
Webpacker 5 will also require Rails 5.2 & above and Ruby 2.4 & above. This change is inline with the Rails maintenance policy.
Multiple files per entry
Rails recommends that Webpacker should only be used for the JavaScript code. The CSS and other assets should be managed by the Asset pipeline. But Webpacker also supports managing CSS. Before Webpacker 5.0, to manage the CSS using Webpacker, following steps need to be performed.
- Add CSS in
app/javascript/scss/application.css
- Import the CSS in the application pack -
import '../scss/application.css'
- Use
stylesheet_pack_tag 'application'
in the layout to load the CSS in Rails views.
But this leads to confusion as the CSS is not treated as entry point
or pack
but instead imported in a JavaScript pack
.
Checkout my article on Mastering packs to know more about packs and entrypoints.
Asset pipeline allows generating separate bundles for CSS and JavaScript. Similarly, webpack supports multiple types of files per entry to generate separate bundles for JavaScript and CSS. Let's say we have a home
layout and accounts
layout in our Rails app and have page specific JavaScript and CSS for these two layouts.
Using webpack, we can specify the CSS and JavaScript files per entry as follows.
# webpack.config.js
...
entry: {
home: ['./home.js', './home.scss'],
account: ['./accounts.js', './accounts.scss'],
}
...
This webpack configuration generates home.js
, home.css
, accounts.js
and accounts.css
as output. Then we can include the individual output files in the individual pages for home
and accounts
. This feature was not supported in Webpacker earlier.
In Webpacker 5, the support for specifying multiple files per entry is added. We don't have to add any configuration for it. We just have to create the multiple files per entry in the app/javascript/packs
directory.
So in this case, we will create following files in the packs
directory.
# app/javascript/packs
accounts.js
application.js
home.js
accounts.css
home.css
We also have to set the extract_css
option as true
in config/webpacker.yml
.
Theextract_css
option tells webpack to generate a separate output file for CSS packs. This option is set tofalse
in development environment so it needs to explicitly changed totrue
to generate the CSS bundles in development.
Once this is done, then the asset pre-compilation will generate the separate JavaScript and CSS bundles for home
and accounts
assets as follows.
{
"accounts.css": "/packs/css/accounts-c5080fd3.css",
"accounts.js": "/packs/js/accounts-a40e36aac42a1276f57d.js",
"accounts.js.map": "/packs/js/accounts-a40e36aac42a1276f57d.js.map",
"application.js": "/packs/js/application-81fbdc52ed23d5b18118.js",
"application.js.map": "/packs/js/application-81fbdc52ed23d5b18118.js.map",
"entrypoints": {
"accounts": {
"css": [
"/packs/css/accounts-c5080fd3.css"
],
"js": [
"/packs/js/accounts-a40e36aac42a1276f57d.js"
],
"js.map": [
"/packs/js/accounts-a40e36aac42a1276f57d.js.map"
]
},
"application": {
"js": [
"/packs/js/application-81fbdc52ed23d5b18118.js"
],
"js.map": [
"/packs/js/application-81fbdc52ed23d5b18118.js.map"
]
},
"home": {
"css": [
"/packs/css/home-f7b12d47.css"
],
"js": [
"/packs/js/home-97c9afb755be496f3c2f.js"
],
"js.map": [
"/packs/js/home-97c9afb755be496f3c2f.js.map"
]
}
},
"home.css": "/packs/css/home-f7b12d47.css",
"home.js": "/packs/js/home-97c9afb755be496f3c2f.js",
"home.js.map": "/packs/js/home-97c9afb755be496f3c2f.js.map"
}%
We can then use these bundles in the layout files as follows.
// app/views/layouts/home.html.erb
<!DOCTYPE html>
<html>
<head>
<title>YankNotifier</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'home', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'home' %>
</head>
<body>
<%= yield %>
</body>
</html>
Using Webpacker 5 in our Rails apps
Update the webpacker
gem in the Gemfile
.
gem 'webpacker', '~> 5.0'
We will also need to update the Webpacker node package as follows.
yarn upgrade @rails/webpacker --latest
Now we are ready to roll with Webpacker 5!
Want to stay current with Webpacker and Rails? Subscribe to my newsletter or follow me on Twitter.