Rails 7 has “three great answers to JavaScript,” but the one answer I want to focus on is the set of bundling gems that are available: jsbundling-rails and cssbundling-rails. These are very slim gems that provide a very conventional way to bundle assets for a modern Rails application by delegating it all to scripts in your package.json
file.
This is the gist of the cssbundling gem. It’s just a rake task that is added to the assets:precompile
task.
namespace :css do
task :build do
system "yarn install && yarn build:css"
end
end
Rake::Task["assets:precompile"].enhance(["css:build"])
And it expects yarn build:css
to put your compiled stylesheet in /app/assets/builds/application.css
, and if you’re using Sprockets, the builds
directory needs to be added to your assets manifest.js
file.
That’s it.
All the heavy lifting is done by what you’ve configured build:css
to do. And the jsbundling-rails gem is nearly identical, except it calls build
in your package.json
file.
Delegating the asset compilation to front-end tooling means you can follow the setup guides for Tailwind CSS or ESBuild without much thought as to how either should work with Rails.
The “magic” happens with Sprockets knowing about these files through the manifest configuration file.
There are some drawbacks to this setup. Changes you make to your source files are not picked up automatically in development in your rails server
process like the traditional Rails assets pipeline. You will need an external process watching your source files for changes and putting the compiled changes in the builds
directory.
Both bundling gems setup a Procfile.dev
and a bin/dev
executable that will delegate running rails server
and your building script(s) in watch mode concurrently to the foreman gem.
At my work, we don’t use yarn, so we’ve actually recreated these gems as a simple rake file in our project that calls npm
instead. Normally I would be against recreating the functionality of a gem and taking on the maintenance burden, but these gems do so little in practice.
These gems are a breath of fresh air compared to the now retired Webpacker gem. They stay true to the convention over configuration mantra of Ruby on Rails and will not add a brittle component to your asset pipeline that will cause you worry as Rails or your preferred asset libraries get updated.