The import-maps gem finally allows us to get rid of JavaScript tooling in our Ruby on Rails projects, whether it’s esbuild or webpacker.
Let’s see together how to convert a project using esbuild, in my case, to import-maps.
Initial State
Our layout links the application.js
and application.css
files.
# views/layouts/application.html.erb
<head>
<!-- ... -->
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
</head>
The CSS file imports styles from various NPM packages located in the node_modules
directory as well as TailwindCSS directives.
@import "notyf/notyf.min";
@import "trix/dist/trix";
@import "actiontext.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
And the JS file imports different packages as well as our Stimulus controllers.
import "@hotwired/turbo-rails";
import "trix";
import "@rails/actiontext";
import "./controllers";
A setup that couldn’t be more classic.
Installing import-map
If your app wasn’t created with Rails 7+, run the commands below to install the gem.
$ bundle add importmap-rails
Then:
$ bundle exec rails importmap:install
You will find the new importmap.rb
file in the config
directory, which somewhat replaces the package.json
file that read our NPM dependencies.
There, you’ll find a list of pins
.
Packages can be loaded from several sources:
- A URL:
pin "notyf", to: "https://ga.jspm.io/npm:notyf@3.10.0/notyf.es.js"
- A gem:
pin "@hotwired/turbo-rails", to: "turbo.min.js"
- A local file:
pin "application"
- A local directory:
pin_all_from "app/javascript/controllers", under: "controllers"
Update
The import-map
installation has already prefilled the importmap.rb
file for you.
You should find there the @hotwired/stimulus-loading
pin, which is a new method of loading for Stimulus controllers that doesn’t require manually registering them.
You can now pin 🍆 your NPM packages to include them in the import list.
$ ./bin/importmap pin notyf
This command will automatically add all the dependencies of the notyf package.
Here’s the list of pins for me:
# config/importmap.rb
pin "application", preload: true
pin "i18n", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/utils", under: "utils"
pin_all_from "app/javascript/controllers", under: "controllers"
pin "trix"
pin "@rails/actioncable", to: "https://ga.jspm.io/npm:@rails/actioncable@7.1.1/app/assets/javascripts/actioncable.esm.js"
pin "@rails/actiontext", to: "actiontext.js"
pin "notyf", to: "https://ga.jspm.io/npm:notyf@3.10.0/notyf.es.js"
You can now modify your layout to load the import-maps.
# views/layouts/application.html.erb
<head>
<!-- ... -->
<%= stylesheet_link_tag "trix",
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
“We are now loading CSS files manually and one by one, to avoid having a single large bundle and to leverage the capabilities of HTTP 2 for loading multiple files quickly.
Cleanup
You can now delete all the files related to JavaScript tooling:
$ rm -rf package.json yarn.lock node_modules
Welcome to a rational world without all the complexity of frontend tools! 🥳
If you want to react to this article or need assistance with updating your Ruby on Rails applications, contact me on LinkedIn, Mastodon.”