DEV Community

Alessandro Rodi
Alessandro Rodi

Posted on • Updated on

Rails 7, Bootstrap 5 and importmaps without nodejs

Our goal: remove nodejs

As many other people in the Rails community, I started setting up brand new Rails 7 projects, and I need to re-learn, at least partially, how to bundle the assets and distribute them.

I never fell in love with TailwindCSS, and therefore I usually setup my Rails apps to use Bootstrap as default.

But what I really like about Rails 7, is the idea of being able to get rid of not only webpack, but of nodejs entirely. The new importmaps feature is really appealing to me and I'd like to use it as long as I don't need to bundle my javascript.

I have to say that esbuild does already a pretty cool job compared to webpack to simplify our lives, and make the process faster, but as long as I don't need bundling, I'd like to not have a package.json file and being dependent on nodejs for my Rails app.

A pure and simple sprockets + importmaps app with no Foreman, no bin/dev, no yarn build --watch stuff.

Bootstrap is made of two parts: CSS and javascript. So I want to use importmaps for the javascript part and rely on sprockets for the CSS compilation from SCSS.

Rails default

By default, Rails 7 provides a new option --css=bootstrap,
but with my great surprise, this option adds both jsbundling-rails, cssbundling-rails, a package.json and esbuild.

Not as expected. Not what I want.

How to configure Rails and Bootstrap without nodejs

Default is not what I want, but I can still reach the goal and here I'll explain how:

Stick with just rails new myapp
This will setup exactly the tools I want: sprockets and importmaps. It will also setup automatically for me stimulus and turbo, which is great because I use them most of the time anyway.

Add bootstrap gem and enable the gem sassc-rails in the Gemfile. This will allow us to compile bootstrap from SCSS without node.

You can simply import Bootstrap styles in app/assets/stylesheets/application.scss:

// here your custom bootstrap variables...
@import "bootstrap";
Enter fullscreen mode Exit fullscreen mode

That's it for the CSS part. Running rails assets:precompile will generate what you want.

For the javascript part we need to do three things:

  • Precompile the bootstrap.min.js that comes with the gem, by adding to config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( bootstrap.min.js popper.js )
Enter fullscreen mode Exit fullscreen mode
  • pin the compiled asset in config/importmap.rb:
pin "popper", to: 'popper.js', preload: true
pin "bootstrap", to: 'bootstrap.min.js', preload: true
Enter fullscreen mode Exit fullscreen mode
  • Include bootstrap in your app/javascript/application.js:
import "popper"
import "bootstrap"
Enter fullscreen mode Exit fullscreen mode

I prefer this approach rather than pinning a CDN because we avoid diverging versions of Bootstrap.

Conclusion

This is all you need to have Bootstrap fully working on Rails 7 without using node.

If you like this guide you can follow me on Twitter.

Discussion (21)

Collapse
hashmaster3k profile image
Hashim G

Great write up Alessandro. What I don't understand is if import maps loads libraries via CDN, why is the Bootstrap gem still needed? You could load Bootstrap straight into the header without all this hassle.

Collapse
coorasse profile image
Alessandro Rodi Author

Hi Hashim,
yes, correct. You could load Bootstrap Javascript part through CDN, but you would still need the gem to use the SCSS stylesheets and customise it. Now, since you have the gem, I think is wise to use also the JS wrapped within the gem, so that you don't risk having divergent versions (one from CDN and one from the Gem).
Of course, if you don't need to customise bootstrap, then you can load everything from CDN.

Collapse
indikaimk profile image
indikaimk

Tried the whole day to get Bootstrap working with Rails 7.
This method works awesome.

Collapse
b1naryman profile image
b1naryMan

Excellent and helpful article. Thanks Alessandro

Collapse
mtnbiker profile image
Greg S

Thank you. Clears up a lot of confusion. The dependancies and/or defaults of the Rails 7 options aren't clear.

Another confusion for me. Is Sprockets the way forward or?

Probably would help if you showed all your changed or added code. Would help avoid the confusion @ochupa faced.

Collapse
duarme profile image
Duccio Armenise

Thanks bro.

Collapse
linediconsine profile image
Marco A.

In application.js :

import "popper"
import "bootstrap"
Enter fullscreen mode Exit fullscreen mode

give this error for me on browser :

GET http://127.0.0.1:3000/assets/popper net::ERR_ABORTED 404 (Not Found)

GET http://127.0.0.1:3000/assets/bootstrap net::ERR_ABORTED 404 (Not Found)

Enter fullscreen mode Exit fullscreen mode

full error log:

GET http://127.0.0.1:3000/assets/bootstrap net::ERR_ABORTED 404 (Not Found)
VM167 application-afa54e21226316d7c1dc5bb51d77586423db47a2adf4ce6a3fc09888e5eda505.js:2 Uncaught SyntaxError: Cannot use import statement outside a module (at VM167 application-afa54e21226316d7c1dc5bb51d77586423db47a2adf4ce6a3fc09888e5eda505.js:2:1)
application-afa54e21226316d7c1dc5bb51d77586423db47a2adf4ce6a3fc09888e5eda505.js:2 Uncaught SyntaxError: Cannot use import statement outside a module (at application-afa54e21226316d7c1dc5bb51d77586423db47a2adf4ce6a3fc09888e5eda505.js:2:1)
application-afa54e21226316d7c1dc5bb51d77586423db47a2adf4ce6a3fc09888e5eda505.js:2          GET http://127.0.0.1:3000/assets/popper net::ERR_ABORTED 404 (Not Found)
Enter fullscreen mode Exit fullscreen mode
Collapse
linediconsine profile image
Marco A.

I miss the

bundle add bootstrap

Collapse
ochupa profile image
ochupa • Edited on

Hey Alessandro, I'm trying to add 'bootstrap-rails' gem but getting error - Could not find gem 'bootstrap-rails' in rubygems repository rubygems.org/ or installed locally.
Could help with the proper name of bootstrap gem?

Collapse
janisleuenberger profile image
Janis Leuenberger

I think he is talking about github.com/twbs/bootstrap-rubygem. Therefore the gem name is just 'bootstrap'.
Correct me if I'm wrong.

Collapse
jmschp profile image
Miguel Hargreaves Pimenta • Edited on

Hey!

I think this could be made simpler.
I believe the bootstrap-rubygem already injects in the assets throughs sprockets the bootstrap.min.js and SCSS files, and also the poper.js through the dependency popper_js-rubygem.

So, in terms of the JS files, all we need to do, after bundeling the bootstrap-rubygem, is import them in the application.js

import "./popper";
import "./bootstrap.min";
Enter fullscreen mode Exit fullscreen mode

I have this working in development.

Collapse
eliblocks profile image
Eli Block • Edited on

Thanks for the guide! I believe it should be

pin "@popperjs/core", to: 'popper.js', preload: true
Enter fullscreen mode Exit fullscreen mode
Collapse
jmschp profile image
Miguel Hargreaves Pimenta

Actually it's not. The bootstrap gem dependes on the popper_js gem

Bootstrap tooltips and popovers depend on popper.js for positioning. The bootstrap gem already depends on the popper_js gem.

Collapse
skrobul profile image
Marek Skrobacki

Don't think this really "works without node" - bootstrap gem does not work if there is no execjs runtime (just try removing executable permission from your NodeJS installation on the system) because autoprefixer needs it. Is there some magic way to force it to use something else?

Collapse
coorasse profile image
Alessandro Rodi Author

Good point! Yes, you can also use another runtime: github.com/ai/autoprefixer-rails#u...

Collapse
josephmo_91 profile image
Joseph Mouhanna • Edited on

The initial tutorial works fine. However, if I copy the application to another folder, and delete all the parts that normally do not make it into GitHub (using a rails .gitignorefile), then run: bundle install, followed by a rails s command, then go to 127.0.0.1:3000/, I get the following error:

Showing /Users/joseph-mac/ProxLearn/Development/PLIConnectV2/repositories/pli2-no-node/app/views/layouts/application.html.slim where line # raised:

link_tree argument must be a directory
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js

Collapse
wafcio profile image
Krzysztof Wawer

There should be bootstrap gem instead of bootstrap-rails gem

Collapse
minhtoandev profile image
Minh Toàn

Helpful

Collapse
zhenyat profile image
ZT

Thx Alessandro! Following your approach I have added Simple Form:
gem 'simple_form'
and run the command:
bin/rails generate simple_form:install --bootstrap
It works fine.

Collapse
akontopoulos profile image
a-kontopoulos

popper.js is not running when I install Bootstrap with this method. However bootstrap.js is working. Any ideas why?

Collapse
coorasse profile image
Alessandro Rodi Author

too few details, sorry. I'd suggest opeining a question on stackoverflow with more details.