Importmap is a great tool, but unfortunately it isn’t a silver bullet for everything. I decided to move away from importmap to esbuild for one of my projects because of it was so tricky to setup it to use with flowbite. Also, I’ll migrate from tailwindcss-rails to cssbundling-rails to make it consistent. Here’s a guide how to perform this migration.
Firstly, let’s update our Gemfile
.
gem "propshaft"
- gem "importmap-rails"
- gem "tailwindcss-rails"
+ gem "jsbundling-rails"
+ gem "cssbundling-rails"
gem "turbo-rails"
gem "stimulus-rails"
Next step - create package.json
in the project root.
{
"name": "app",
"private": true,
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"devDependencies": {
"esbuild": "^0.24.0"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets",
"build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify"
},
"dependencies": {
"@hotwired/stimulus": "^3.2.2",
"@hotwired/turbo-rails": "^8.0.12",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.16"
}
}
and of course we need node
and yarn
installed to run
yarn install
Don’t forget to add other libraries you use in your project which is referenced in your config.importmap.rb
. After that, you can simply remove this file. Next stop - javascript files. Let’s update app/javascript/application.js
:
- // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
+ // Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
- import "controllers"
+ import "./controllers"
Next app/javascript/controllers/index.js
- // Import and register all your controllers from the importmap via controllers/**/*_controller
- import { application } from "controllers/application"
- import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
- eagerLoadControllersFrom("controllers", application)
+ // This file is auto-generated by ./bin/rails stimulus:manifest:update
+ // Run that command whenever you add a new controller or create them with
+ // ./bin/rails generate stimulus controllerName
+
+ import { application } from "./application"
If you’ve added stimulus controllers, you may need to run
./bin/rails stimulus:manifest:update
Let’s update layout app/views/layouts/application.html.erb
- <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
- <%= javascript_importmap_tags %>
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
+ <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
Our next step is to do some updates for stylesheets. You can remove app/assets/stylesheets/application.css
, but don’t forget co copy your styles to app/assets/stylesheets/application.tailwind.css
in case if you’ve added something. Then move config/tailwind.config.js
to the project root. You may need to add missing tailwind plugins:
yarn add @tailwindcss/forms @tailwindcss/typography @tailwindcss/container-queries
Update Procfile.dev
to add esbuild for JS and replace tailwind gem with node package with similar name :)
web: bin/rails server
- css: bin/rails tailwindcss:watch
+ js: yarn build --watch
+ css: yarn build:css --watch
Well, looks like we’ve done. Let’s check our app with
bin/dev
Everything should work fine. You may also need to
- update
.github/workflows/ci.yml
- update
.gitignore
- update
Dockerfile
and.dockerignore
- remove
bin/importmap
- remove unused stuff from
vendor
But I believe you can do it without my help :)