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
.nvmrcwith your preferred node version (and install it) - add gems
jsbundling-railsandforemanto yourGemfile:gem 'jsbundling-rails' group :development, :test do gem 'foreman' # ... end bundle install- run
bin/rails javascript:install:esbuildin a console to prepare esbuild. - run
yarn installto 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.jsin 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.jsonto 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
importstatements 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
@importstatements 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.precompilethat are no longer necessary, because you now load those libraries through esbuild. - adapt your
app/assets/config/manifest.jsfile 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:precompileand 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:clobberto remove the precompiled assets again. - adapt your
stylesheet_link_tagandjavascript_link_tagto match the new pack names. - start the development server with the command
bin/devand check that everything works and looks good.
Finish
- remove gems from your Gemfile that are no longer necessary, e.g.
sass-railsoruglifier - 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)