This are the steps I needed to do to add esbuild to an application that used the vanilla rails asset pipeline with sprockets before.
Preparations
- update Sprockets to version 4
- add a
.nvmrc
with your preferred node version (and install it) - add gems
jsbundling-rails
andforeman
to yourGemfile
:gem 'jsbundling-rails' group :development, :test do gem 'foreman' # ... end
bundle install
- run
bin/rails javascript:install:esbuild
in a console to prepare esbuild. - run
yarn install
to install all packages so far - add the plugins for esbuild you're going to need:
yarn add esbuild-plugin-import-glob yarn add esbuild-sass-plugin
- create
esbuild.config.js
in the root folder of your project. A minimal config could look like this (kudos to Arne Hartherz):const railsEnv = process.env.RAILS_ENV || 'development' const optimize = railsEnv !== 'development' const path = require('path') const { default: importGlob } = require('esbuild-plugin-import-glob') const { sassPlugin } = require('esbuild-sass-plugin') require('esbuild') .build({ entryPoints: [ 'application.js', ], bundle: true, outdir: path.join(process.cwd(), 'app/assets/builds'), absWorkingDir: path.join(process.cwd(), 'app/assets'), color: true, minify: optimize, sourcemap: true, plugins: [ importGlob(), sassPlugin({ cache: true }), ], })
- Add error handling
- adapt your
package.json
to use your config file for the build command:"scripts": { "build": "node esbuild.config.js" }
Transform your existing build pipeline to use esbuild
- adapt your entryPoints for esbuild in
esbuild.config.js
. This will be your pack names. E.g.:require('esbuild') .build({ entryPoints: [ 'frontend.js', 'backend.js', ], // ... (more config)
- create files for your entry points and add
import
statements to import everything you need, e.g.frontend.js
:import './frontend/stylesheets/base.sass' import './frontend/stylesheets/blocks/**/*.sass' import 'unpoly/unpoly.js' import 'unpoly/unpoly.css'
- run
yarn build
(oryarn build --watch
) and resolve all errors.- You probably have to adapt at least your sass
@import
statements to use relative paths. - dart-sass has some differences compared to node-sass. If you run into problems that are not easy to resvole, you can switch to use node-sass with esbuild. See here Show archive.org snapshot - you have to downgrade esbuild-sass-plugin to 1.x for that, because 2.x does not support node-sass anymore.).
- You probably have to adapt at least your sass
- add libraries, that were loaded via gem previously, to your package with
yarn add
(e.g.yarn add bootstrap@4.5.0
). Note that esbuild might complain if there are references to fonts or images in a libraries' css, because it can't load them. Tell esbuild to ignore them by marking them as external inesbuild.config.js
:During the next steps you have to make sure that sprockets serves them correctly and rewrites the paths if necessary.external: ['*.ttf'],
Prepare Sprockets to serve the assets bundled via esbuild
- remove entries for
Rails.application.config.assets.precompile
that are no longer necessary, because you now load those libraries through esbuild. - adapt your
app/assets/config/manifest.js
file to include only the folders that sprockets needs to take care of, e.g.:Also add library fonts or images there.//= link_tree ../builds/ //= link_tree ../fonts/ //= link_tree ../images/
- Write your own Sprockets postprocessors if you have to rewrite paths to assets.
- run
rails assets:clobber assets:precompile
and resolve all errors.
Check the generated CSS and JS files in the public folder if all paths were resolved correctly and also use the correct digest. - when there are no errors any more, run
rails assets:clobber
to remove the precompiled assets again. - adapt your
stylesheet_link_tag
andjavascript_link_tag
to match the new pack names. - start the development server with the command
bin/dev
and check that everything works and looks good.
Finish
- remove gems from your Gemfile that are no longer necessary, e.g.
sass-rails
oruglifier
- run your test suite and make sure that all tests succeed.
- optional: Make your application show esbuild errors
Tipps for Troubleshooting
Try to check things one at a time. Does esbuild create your packages and move them to the destined folder (yarn build --watch
)? If yes, does Sprockets move that file to the public
folder (rake assets:precompile
and rake assets:clobber
)? Are the paths and digests correct?
Posted by Judith Roth to makandra dev (2022-01-25 10:27)