Rails new has new options. They are
Remember, if you want parity with what you were familiar with in Webpacker under Rails 6, using jsbundling-rails with the new faster esbuild is the way to go for you.
This article will help you if you’ve already decided you don’t want ImportMap. To help make that decision, check out Rails 7 : Do I need ImportMap-rails
Bundling also requires that you run a “watcher” in the background so that as you develop SCSS or Typescript your changes are immediately recompiled by the watcher and visible in your development environment.
IMPORTANT: Do not attempt to add jsbundling-rails on top of an app created with rails new (importmap). Do not attempt to create a new Rails app with cssbundling-rails and then add jsbundling-rails after. Do not attempt to switch between jsbundling-rails and Importmap on new Rails installations.
Section 1: Meet the CSS and JS Flags
If you use either the
--css or the
--js flag, you will get both cssbundling and jsbundling. However, if you use one or the other, the next one becomes more tedious to set up. Therefore, I recommend you always start with both
Your JS choices are: ESBuild, Rollup, and Webpack. For CSS, see Section 2 of this article.
Now make sure to use the new
./bin/dev instead of the old
rails server or else your JS & CSS will not compile.
On the project folder you now start your Rails server and a background “watcher” with:
Confirm ESBuild Loads the Rails 7 Features
1. Confirm that Stimulus works
Uncomment this line in
Rails.application.routes.draw do root "articles#index" end
Generate an articles controller
rails generate controller Articles
Now create a file at app/views/articles/index.erb
Boot rails using
DO NOT BOOT RAILS USING THE OLD
rails server METHOD
Confirm that you see the “Hello world!” on the screen.
You can do this one of two ways
Generating the controller using the Rails helper:
./bin/rails generate stimulus controllerName
When generated this way, you will automatically be modifying the manifest file.
If you create the Stimulus controller by hand, run this command to update your manifest file:
2. Confirm that Turbo is Working
Go back to
routes.rb and add this line. This is non-standard, do not do this in a real Rails app!
Rails.application.routes.draw do post "/", to: "articles#index" root "articles#index" end
Now go back to app/views/articles/index.erb
You can leave the Stimulus test in place, and add this form:
<div data-controller="hello"></div> <%= form_with(url: "/") do |form| %> this is a form for you to submit <%= form.text_field :xyz %> <%= form.submit "submit" %> <% end %>
Now, load your browser window and you will see the new form.
If Turbo Rails is NOT installed correctly, you will see this:
WRONG: This is what happens when you first boot without the “watcher” running — Stimulus & Turbo are not enabled
Notice that this form submission — which does absolutely nothing— should be sent to the Rails backend as a
TURBO_STREAM, not as an
CORRECT: This is what happens when you boot using the new
./bin/dev rails command, which includes running webpack in the background to compile your JS.
You must see the request submitted as
TURBO_STREAM or else Turbo will not be working correctly.
Please note that obviously, even if Turbo is working, this app doesn’t actually do anything. The only purpose of this exercise is to examine your Rails logs for the TURBO_STREAM requests from the frontend.
Section 2: Bundling app with With Bootstrap & ESBuild
If you started with section 1, you can archive that work and start again here.
1. Hello sassc-rails Gem
Start by uncommenting the scssc-rails gem which is commented out by default in the Gemfile:
2. Turn on Inline Source maps (so we can debug Rails 7 Bootstrap)
in config/environments/development.rb add this line:
config.sass.inline_source_maps = true
3. Add a (temporary) Dummy Controller & Route
Create the articles controller with:
rails generate controller Articles
Add an empty def index to it:
class ArticlesController < ApplicationController def index end end
in config/routes.rb, uncomment this line:
And finally, create a Hello World file at app/views/articles/index.erb
Now, load your website in your browser and click “View Source”
Notice here that Sprockets has applied a thumbprint to this specific build. When we change anything in our CSS, Sprockets will recompile the application file and give it a new thumbprint.
7. Now add Something for Rails 7 Bootstrap
If we look in our browser, our existing layout looks like so:
The shrewd eye might notice that Bootstrap is in fact applied (you can tell because the font is not the browser’s default), but we would hardly notice since all our app does is say “Hello World”‘
So let’s add a Bootstrap navbar:
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container-fluid"> <a class="navbar-brand" href="#">Navbar</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link active" aria-current="page" href="#">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> Dropdown </a> <ul class="dropdown-menu" aria-labelledby="navbarDropdown"> <li><a class="dropdown-item" href="#">Action</a></li> <li><a class="dropdown-item" href="#">Another action</a></li> <li><hr class="dropdown-divider"></li> <li><a class="dropdown-item" href="#">Something else here</a></li> </ul> </li> <li class="nav-item"> <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a> </li> </ul> <form class="d-flex"> <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success" type="submit">Search</button> </form> </div> </div> </nav>
Ok now let’s take a look:
Notice that when you hit the Hamburger menu, the other options slide down.
Even though jQuery is available to Bootstrap here via importing it through the Webpack dependency management, jQuery is not globally available as was custom with old-style Rails development.
Hence, if you open your console browser and type jQuery, you will see:
This is the expected result as jQuery is not globally available on your page