Ask A Question

Notifications

You’re not receiving notifications from this thread.

How to use ESBuild in Rails with JSBundling Discussion

This is awesome, I have been using it for a couple of weeks now. I didn’t necessarily think webpacker was slow, except maybe on Heroku builds. But when you use this, you wonder why you put up with webpacker for so long :)

Reply

I had the exact same thoughts!

Reply

Exactly. Working with Webpacker was painful compare to ESBuild. I'm really enjoying the workflow and process with Rails 7 new features.

Speaking of which, wouldn't you use importmap instead of dealing with JS complexity?

Reply

Does it make sense to have esbuild-rails built into Rails? And should the esbuild.config.js file go in the /config folder or do files in that folder have to be Ruby?

Reply

Not really. They tried that with webpacker and it didn't work because things change so often and every app needs flexibility to adjust for their use case.

The way JSbundling is setup, you can use any tools you want. The only requirement is they dump to the asset pipeline. That's super flexible and you can make any changes you need. Great balance I'd say.

Reply

you can do so with bundling or code-splitting, plugins, and more.

Reply

I am trying to run away from my webpack. Is it possible to handle react with jsx plus scss files imported ? Especially, scss files are located in app/javascript ?

Reply

JSX/React, yeah esbuild actually comes with support for JSX and typescript I believe, all built in with no configuration needed.

As far as SCSS is concerned, the best approach would be to use cssbundling-rails and have a separate build task just for the SCSS files. You could point this task to app/javascript/styles/app.scss or similar, it just needs to output the built file to app/assets/builds/*.css.

Reply

Thanks for your comment !

Reply

You may even consider looking into vite-ruby.
Vite uses esbuild for building the JS, but it also lets you build your CSS just as fast with built in live reloading.

Reply

This is great. Super easy to use and I don't feel like I have to dedicate a month to reading about optimization like webpacker.

The only problem I'm having is that, with an application loaded with controllers, the application.js build gets large pretty quickly. With webpacker, I used a plugin that spit out entrypoints for each controller, so that I could use them on a page-by-page basis (and also import third-party libraries within those controllers to avoid large packs).

I took a look at the esbuild documentation and was able to get sourcemaps by adding sourcemaps: true to the build in esbuild.config.js (using esbuild-rails). I tried splitting: true, format: "esm" but some of my controllers stopped working in unpredictable ways. I gather that it's still very much a work in progress.

I'm trying to wrap my head around a way to separate those controllers without creating import files for each.

Reply

It is so fast that I thought it wasn't working and something was wrong.

Reply

Haha! I know right? So happy with how fast my deploys are now.

Reply

I'm not really huge into js, just want to sprinkle a few bits of ujs/stimulus/jquery type stuff in there and I usually find thats enough to get a lot done. Its been bewildering recently with webpacker to get simple stuff working at times. thanks for this video explaining more of whats going on.

Reply

Is it possible to include coffeescript files into our application.js using this new js bundling system?

I'm trying to import like this:
import "./trixmodz"

My file is here:
app/javascript/trixmodz.coffee.erb

but get an error

[watch] build finished
20:01:04 js.1 | [watch] build started (change: "app/javascript/admin.js")
20:01:04 js.1 | ✘ [ERROR] Could not resolve "./trixmodz"
20:01:04 js.1 |
20:01:04 js.1 | app/javascript/admin.js:13:7:
20:01:04 js.1 | 13 │ import "./trixmodz"
20:01:04 js.1 | ╵ ~~~~~~~~~~~~

Reply

I keep getting the following routing error, but it looks like it's compiling correctly, maybe?

ActionController::RoutingError (No route matches [GET] "/assets/application.js-9dcbd890262770cf8651cbbfafa5b33aa1a83c242962fe28a6539c5725786e6d.map"):

Reply

I'm getting errors for sourcemaps on every request as well. I'm not sure why it's happening, but I assume it's because I'm using a non-stock configuration. i.e. I'm building two scripts - application.js and application-dev.js (only used in dev).

My scripts section for dev looks like:

"dev": "concurrently --kill-others yarn:dev:*",
"dev:css": "tailwindcss --watch -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css",
"dev:js": "esbuild app/javascript/application.js --watch --bundle --sourcemap --outfile=app/assets/builds/application.js",
"dev:jsdev": "esbuild app/javascript/application-dev.js --watch --bundle --sourcemap --outfile=app/assets/builds/application-dev.js",

and in my Procfile.dev:
assets: yarn dev

Reply

Hmm. Are you using hotwire-livereload? I just updated that gem (1.1.0) and my sourcemap errors are gone.

Reply

I get the same error @luis. Did you manage to fix it?

Reply

Hi! I wanted to watch this episode but got this error "This stream is not available anymore"
(I'm not sure whether you will get the exactly same error message, I translated it from Russian "Эта прямая трансляция больше не доступна.")

Reply

Sorry, false alert - browser issue:) works fine from Safari. Apparently problem is caused by one of Chrome extensions

Reply

Hi, the production deployment is failing for me. I'm using Capistrano for the deployment, below you can find the details.

jsbundling-rails: Command build failed, ensure yarn is installed and `yarn build` runs without errors
/home/deploy/truemango/shared/bundle/ruby/3.1.0/gems/jsbundling-rails-1.0.2/lib/tasks/jsbundling/build.rake:5:in `block (2 levels) in <main>'
/home/deploy/truemango/shared/bundle/ruby/3.1.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/home/deploy/.rbenv/versions/3.1.1/bin/bundle:25:in `load'
/home/deploy/.rbenv/versions/3.1.1/bin/bundle:25:in `<main>'
Tasks: TOP => assets:precompile => javascript:build

Do I have to add any Capistrano task?

Please help me to resolve this issue.

Thanks.

Reply

Any luck on this? I am having the same issue on Heroku.

Reply

I'm loving this episode! Thanks for the help.

Reply

This works great, but I'm having trouble getting esbuild to pick up css from node modules. Do you have any suggestions?

Reply

I keep running into this issue when I run ./bin/dev
everything else seems to run

Error: Can't find stylesheet to import.
16:49:51 css.1 | ╷
16:49:51 css.1 | 1 │ @import 'bootstrap/scss/bootstrap';
16:49:51 css.1 | │
16:49:51 css.1 | ╵
16:49:51 css.1 | app/assets/stylesheets/application.bootstrap.scss 1:9 root stylesheet

Rails 7.0.4
Ruby ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin20]
yarn 3.2.3
npm -v 8.19.1 not sure if this is even needed

application.css
/* Error: Can't find stylesheet to import.

  • ,
  • 1 | @import 'bootstrap/scss/bootstrap';
  • |
  • '
  • app/assets/stylesheets/application.bootstrap.scss 1:9 root stylesheet */

body::before {
font-family: "Source Code Pro", "SF Mono", Monaco, Inconsolata, "Fira Mono",
"Droid Sans Mono", monospace, monospace;
white-space: pre;
display: block;
padding: 1em;
margin-bottom: 1em;
border-bottom: 2px solid black;
content: "Error: Can't find stylesheet to import.\a \2577 \a 1 \2502 @import 'bootstrap/scss/bootstrap';\a \2502 \2575 \a app/assets/stylesheets/application.bootstrap.scss 1:9 root stylesheet";
}

any ideas

Reply

@PatJames
// /app/assets/stylesheets/application.scss
@import 'bootstrap';

// /app/assets/stylesheets/bootstrap.scss
@import 'bootstrap/scss/bootstrap';

// /app/javascript/application.js
// Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"

I have been looking at Rails 7 and am now working on trying to upgrade an app using importmaps. In other words I don't have a big app working with esbuild. My notes on say what I put in above is based on https://www.bootrails.com/blog/rails-7-bootstrap-5-tutorial/.

Reply

esbuild builds js faster, but it looks like a bundle size is not a priority for it. I used the approach from the lesson and ended up with ~100MB application.js as a result. Not sure if I can call it a production-ready solution 🤷‍♂️.

I have put some details here https://github.com/rails/jsbundling-rails/issues/143.

Reply

As long as you use rails g stimulus new_controller_name updates index.js and create a controller.

Reply

i am on rails 7.1.beta and when i run bin/dev i get this error on console:

15:41:20 js.1 | exited with code 0
15:41:20 system | sending SIGTERM to all processes
15:41:20 css.1 | exited with code

but rails server command works. any idea why?

Reply

I just upgraded an enterprise Rails 6 sprockets 3 app to rails 7, that used webpacker 4 built css and renders react components occasionally. It's about 8 years old so it was the craziest upgrade. I tried shakapacker, vite-rails, esbuild, cssbundling, and pretty much anything in between. What ultimately ended up working was unwinding the scss from webpacker, and then going to sprockets 4 and dartsass-rails. once the site worked exactly the same, I went to jsbundling-rails with esbuild and slowly moved each entrypoint to their new app/javascript folder. I wanted to get the file structure back to a more rails default instead of ui > js > sccs. (although I left all the react-rails files in the ui folders). I didn't need to do any jquery import fixes. I just added //= require jquery3 in the assets/javascripts jquery.js file. Then load javascript_include_tag "jquery" in application.html

I'll probably write up a blog post about challenges of upgrading an app that had over 30 contributors over almost a decade.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 87,400+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.