Experimenting with Importmap for Rails

January 12, 2022

I so want to get rid of Webpacker in all the Rails apps I work on.

Years ago, after switching from Sprockets to Webpacker to manage assets I saw that:

  • assets:precompile started to eat up a lot of time and memory during deploys.
  • Dev asset compilation was noticeably slower, even with webpack-dev-server running.
  • Keeping up with security patches and deprecations in Webpacker and all its dependencies was painful.

I'm excited about the work the Rails crew has been doing to change how CSS is managed and to embrace JavaScript import maps. So I decided to upgrade my blog to test out some of the new gems that are underway.

Switching from Webpacker-managed CSS to cssbundling-rails was nice and easy. I installed the gem and then added in Sass and Bootstrap. It's fast and simple to use yarn build:css --watch to automatically compile Sass into CSS upon changes.

Switching from Webpacker-managed JS to importmap-rails was OK. It did reduce asset compilation time by about 30 seconds. And it cut down yarn.lock to almost nothing.

But depending on the packages you use, you might have to work through some bumps. Bootstrap requires Popper for dropdowns, tooltips, and popovers. importmap-rails currently requires a small workaround in order for Popper to work correctly because the distribution used by JSPM.org isn't the browser-compatible one.

And there was a minor performance toll taken on the initial page load. importmap-rails uses JSPM.org as the CDN to resolve package requests. Not all packages are optimized for import maps yet. After upgrading, the initial page load was making 47 requests to ga.jspm.io, with 46 of these being for separate Popper files (index.js, enums.js, detectOverflow.js, etc.) This added a noticeable slowdown of a few hundred milliseconds to the initial page load. Once the JavaScript was cached, additional page loads took the same time as before.

Because of the slowdown on initial page loads, I ended up switching back to using Sprockets to manually include the minimized version of Bootstrap with Popper for now (bootstrap.bundle.min.js). But I'm looking forward to seeing where this goes in the future.

Pros

  • assets:precompile time was reduced from ~37 seconds down to ~7 seconds.
  • Dev compilation using yarn build:css --watch is fast and simple.
  • The size of yarn.lock changed from 305kb to 6kb so keeping up with patches shouldn't be as painful.

Cons

  • Not all packages provide the CDN with browser-compatible distributions at this time. You may have to work around errors.
  • Depending on how packages are served, the initial uncached page load may require tens of extra requests to the CDN which can be noticeably slow.

References