JSBundling provides a flexible way of using different Javascript bundlers like esbuild, rollup.js or Webpack.
It strikes a great balance between the asset pipeline and webpacker.
jsbundling-rails is a much more lightweight integration.
This gem provides installers to get us going with the bundler of our choice in Rails application,
and a convention to use app/assets/builds to hold our bundled output as artifacts.
The idea behind jsbundling is that we still use Yarn and the package.json file,
but the built bundle goes into the asset pipeline download rather than being controlled by webpack.
Installation
We must already have node and yarn installed on our system.
We will also need npx version 7.1.0 or later.
Then:
-
Add
jsbundling-railsto Gemfile withgem 'jsbundling-rails' -
Run
./bin/bundle install -
Run
./bin/rails javascript:install:esbuild (or replace esbuild with rollup or webpack)
Or, in Rails 7+,
we can preconfigure our new application to use a specific bundler with rails new myapp -j [esbuild|rollup|webpack].
The installer creates an app/assets/build directory,
appends that directory to the asset pipeline manifest at
app/assets/config/manifest.js and .gitignore it.
The jsbundling:install command inserts a javascript_include_tag tag
in our application.html.erb file.
This tag will include the new javascript entrypoint javascript/application.js
for our build script to be included in our application.
Watch Mode
Run the bundler in watch mode in a terminal with yarn build --watch.
Start dev server with foreman start -f Procfile.dev or run rails s and yarn build --watch separately.
We can also use ./bin/dev,
which will start both the Rails server and the JS build watcher.
Whenever the bundler detects changes to any of the JavaScript files in our project,
it’ll bundle app/javascript/application.js into app/assets/builds/application.js.
Production
When we deploy our application to production,
the javascript:build task attaches to the assets:precompile task
to ensure that all our package dependencies from package.json are installed via yarn,
and then runs yarn build to process all the entry points,
as it would in development.
The latter files are then picked up by the asset pipeline, digested,
and copied into public/assets,
like any other asset pipeline file.
We can configure our bundler options in the build script in package.json
or via the installer-generated rollup.config.js
for rollup.js or webpack.config.json for Webpack.
One fantastic thing about jsbundling-rails is even if we decide to use Webpack instead of esbuild
we can easily swap it out, and unlike Webpacker it will use a raw webpack config file.
That was a great decision because I imagine people who want to go all-in with Webpack will want to use their existing configs.
Comparison with webpacker
If we’re already using webpacker,
we may be wondering how it compares to jsbundling-rails
and whether we should migrate or stick with webpacker.
Here are some considerations:
-
jsbundling-railsis a much more lightweight integration.webpackeris more involved and opinionated. -
jsbundling-railscan be used with multiple bundlers (currentlyesbuild,rollup, andwebpackare supported out of the box, but anything that can put a bundle intoapp/assets/buildscould be configured to work with it).webpackeris built specifically to integrate with webpack. -
jsbundling-railsdoesn’t tie us to specific versions of the JavaScript packages we use for bundling, transpiling, etc.webpackerreleases are tied to a specific major version ofwebpack,babel, etc. This means we cannot freely upgrade those packages - we have to wait for a newwebpackermajor release that supports the newer versions, and upgrading to that newwebpackerrelease requires upgrading to all of those new JavaScript package versions at once. -
jsbundling-railsuses the standard configuration format for our bundler of choice.webpackerhas its configuration layer on top of webpack’s configuration, which requires us to do some translation when following guides/documentation written directly for webpack. -
jsbundling-railsworks with the standard actionview asset helpers.webpackerprovides the tag helpers that we need to use. -
webpackercan be used as a complete replacement for sprockets, and in that setup, we can stop loading the sprockets/railtie in our application.jsbundling-rails(as well as css-bundling-rails) works in conjunction with sprockets. -
webpackersupports using a dev server for hot reloading.jsbundling-railshands-off static files to sprockets, so hot reloading is not supported (i.e., to load any JavaScript changes, we’ll need to do a local-state-clearing full page refresh). -
webpackerdelegates asset processing entirely to the external nodejs tooling.jsbundling-railsstill relies on sprockets to output the final public assets and create the associated manifest. When the webpack has full control over the result, it can integrate additional features like automatic code-splitting of statically imported shared dependencies, andwebpackercan load each entry point’s dependent chunks for us. Withjsbundling-rails, we’ll be able to manually split out lazy-loaded chunks by using dynamic import()s.
To know more about this feature checkout this PR.
