20 June 2022

JavaScript in Rails 7

Webpacker is retired, and there are 2 new gems to manage frontend files. JavaScript in Rails 7 will be different.

Rico Sta. Cruz @rstacruz

JavaScript in Rails 7 will be different: the Webpacker gem has been retired, and there are 2 new gems to manage frontend files.

'Webpacker has been retired' screenshot
Webpacker has been retired as of 2022 according to the project’s README.

Life after Webpacker

Webpacker has been retired. Webpacker was the gem that Rails used to integrate Webpack, and Webpacker 5 will be the last version. The Webpacker 6 release candidate is now going to be community-maintained under a new name. (source)

The import-map gem

The importmap-rails gem will come pre-loaded in Rails 7, and seems to be the answer to the question “how do I use npm packages in Rails?”.

import-map readme screenshot on GitHub
importmap-rails is a new gem to integrate JavaScript in Rails without transpiling or bundling.

What is import-map?

Import-map is a lightweight tool to transform imports from npm module names (eg, “react”) into URL’s, useful for loading scripts from an external CDN.

example.js
// Transforms this:
import React from 'react';

// Into this:
import React from 'https://ga.jspm.io/npm:react@17.0.1/index.js';

Importing URL’s?

Yes, using import in the browser is natively supported by all modern browsers—no bundlers needed! Importing URL’s inside a script tag should work. (docs)

esm_example.html
<script type='module'>
  import confetti from 'https://cdn.skypack.dev/canvas-confetti';
  confetti();
</script>
Try this example at skypack.dev.

No compiling

There is no “build” or “compile” step in importmap-rails. There’s no Babel, PostCSS, or anything that transforms JavaScript code.

No bundling

It doesn’t combine many JavaScript files into one, unlike bundlers like Webpack. Rather than serving all files under one application.js, import-map will load all files individually(!).

# While most applications would often serve a bundle
# of JavaScript like this:
https://example.com/assets/application-1a2b3c4d.js
# import-map's approach would be to *not* bundle the
# files, and serve them individually instead:
https://example.com/assets/application-1a2b3c4d.js
https://example.com/assets/components/button-1a2b3c4d.js
https://example.com/assets/components/radio-1a2b3c4d.js
https://example.com/assets/components/dialog-1a2b3c4d.js
https://example.com/assets/components/carousel-1a2b3c4d.js

The jsbundling-rails gem

The jsbundling-rails gem appears born out of the desire to use Webpack alternatives in Rails.

jsbundling-rails readme on GitHub

jsbundling-rails enables support for esbuild, Rollup, Webpack and more.

Lighter than Webpacker

While Webpacker offered very tight integration with Webpack (even its configs are in Ruby and Yaml), jsbundling-rails is a more “lightweight” integration. The main source code is less than 20 lines: all it does is invoke “yarn install && yarn build” before asset precompilation.

Image

esbuild, Rollup, and Webpack

Apart from Webpack, there are other bundlers supported. esbuild is a very fast alternative written in Go, and Rollup is a popular alternative often used with libraries.

Migration from webpacker

Seems straightforward. The goal is to set up Webpack as you would in a Node.js project (eg, work without Webpacker) and that’s it. (github.com: jsbundling-rails migration guide)

Downsides

While jsbundling-rails supports Webpack, not all of its features can be used.

The Shakapacker gem

The work on Webpacker has been continued by ShakaCode and was named for their company. Shakapacker is based off of the unreleased Webpacker 6. (The last Webpacker version is 5.)

Comparing them all

import-mapjsbundlingshakapacker
npm modulesCDN only
Code splitting--
Hot module reloading--
React JSX support-
Delivery to the end userMultiple filesBundledBundled
Tree-shaking optimisation-
Thanks for reading! I'm Rico Sta Cruz, I write about web development and more. Subscribe to my newsletter!