Rails 7 replaces Webpacker with importmapped Hotwire as default JavaScript setup


Rails has a love-hate relationship with JavaScript. However, much of the modern web now wouldn’t exist without JavaScript.

Currently, Rails transpile all Javascript files into a large bundle that the browser can read. This method is outdated since browsers now support reading ES6 directly. Chrome, Edge, Safari, and Firefox fully support ES6. The last major hold out was IE11, but Microsoft mercifully announced its end of life this year.

Before

Since 2017 and Rails 5.2, all Rails applications supported Webpack via Webpacker which allowed compilation to happen almost seamlessly. It was fitting of its era. An era where Javascript developers had to write code, wait for it to compile, and then finally see the result. So much for being modern!

After

There seems to be a wrong notion that Rails developers hate Javascript – they don’t. They just don’t enjoy being tied to the JavaScript ecosystem when working on a primarily Ruby environment. This was essentially the problem Webpacker should have solved by ushering in a suite of Ruby extensions that would have made Webpacker easier to use. Alas, that didn’t happen.

Fortunately, the web now is making it possible to reduce some of the tension surrounding Javascript development in Rails.

  • The first major shift is major browser support for ES6. This completes removes the need for transpiling.
  • The second crucial change is HTTP2. With HTTP2, there is no longer a need to pay a large penalty for sending many small files instead of one big file. A single connection can multiplex all the responses needed. Further reducing the need for one large Javascript bundle file.
  • Finally, we have the era of import maps, which allow the use of logical references for modules in ES6. Previously, every Javascript file after compilation would look something like “main-a6d26cef87d241eba5fa.js”, basically the filename with a digest at the end. This means that every time any small change occurred in that file, it needs to be compiled all over again and create a new digest so that the browser recognizes the update. The answer to this problem is import-maps.

Taking into consideration all the major shifts in modern Javascript development, Rails 7 has decided to replace Webpacker with importmapped Hotwire as default the JavaScript setup.

This means that a default Rails skeleton will not have to require the full JavaScript toolchain with Webpack by default.

Here are the new options,

  1. rails new produces a skeleton configured with importmap-rails, turbo-rails, and stimulus-rails. No Webpack, no Yarn, no package.json, no node. All the integration setup is done through adding the gems, then running importmap:install, turbo:install, stimulus:install tasks.
  2. rails new —skip-hotwire a skeleton-like above but with just importmap-rails configured.
  3. rails new —skip-javascript no JavaScript setup of any kind is configured.
  4. rails new —webpack is essentially what we had on Rails 6.2, with the exception that the default Turbolinks configuration is replaced with Hotwire (both Turbo and Stimulus). This of course includes setting up package.json, Yarn, etc.
  5. rails new —webpack —skip-hotwire is the same as above, minus the default configuration of Hotwire.