Wiring up real-time/live browser code reloads with Tailwind

I’m trying to get my app/environment wired up to achieve the following:

  1. App with Tailwind CSS
  2. Hot reloading in the browser for UI changes
  3. Tailwind-related changes also trigger the hot reload

Why? Well, obviously, to optimize UI development workflow (i.e., no manually reloading browser pages)

Here’s what I’ve figured out by stitching together multiple articles:

FIRST (source: Install Tailwind CSS with Ruby on Rails - Tailwind CSS)

    rails new myapp --css tailwind

NEXT:

Enable browser hot code reloading with GitHub - railsjazz/rails_live_reload: Live Reload for your Rails app. The easiest way to increase your productivity. :

Edit Gemfile, adding:

group :development do
    gem "rails_live_reload"
end

> bundle

FINALLY (source: How to Setup Tailwind 3 on Rails 7 - DEV Community 👩‍💻👨‍💻):

cd myapp
npm install -D tailwindcss
npx tailwindcss init

UPDATE: These next steps may not be required since it looks like the base tailwind setup already has the following:

  1. config/tailwind.config.js
  2. app/assets/stylesheets/application.tailwind.css and <%= stylesheet_link_tag “tailwind”, “inter-font”, “data-turbo-track”: “reload” %> in application.html.erb.

But this leaves:

npx tailwindcss -i app/assets/stylesheets/application.css -o app/assets/stylesheets/wind.css --watch

Which maybe needs to be something like:

npx tailwindcss -i app/assets/stylesheets/application.css -o app/assets/build/tailwind.css --watch

(???) Edit generated tailwind.config.js:

        module.exports = {
            content: ["./app/**/*.{html,js,erb}"],
            theme: {
                extend: {},
            },
            plugins: [],
        }

(???) Edit app/assets/stylesheets/application.css, adding:

@tailwind base;
@tailwind components;
@tailwind utilities;

(???) Edit application.html.erb, adding:

<%= stylesheet_link_tag 'wind', media: 'all', 'data-turbolinks-track': 'reload' %>

In a separate shell:

npx tailwindcss -i app/assets/stylesheets/application.css -o app/assets/stylesheets/wind.css --watch

Now it appears that simple changes to the .erb file (AND tailwind class changes) are automatically reflected in the browser without manually reloading.

The big questions I have:

  • Am I over-complicating/over-thinking this? Is there a simpler way?
  • Am I missing anything critical?

Okay. After some digging, researching, and experimenting I realize this is much simpler than I’ve made it above.

This is where I am now…

FIRST:

rails new my app --css tailwind

Unsurprisingly, this sets up almost everything we need.

However we need two things in order to optimize our UI development workflow a bit by eliminating the need for manually refreshing the browser.

The first step to this is to use the rails_live_reload gem by adding this line:

gem "rails_live_reload"

Into the app’s Gemfile like this:

group :development do
    gem "rails_live_reload"
end

Then run bundle:

> bundle

Now, when you are running (rails s) whenever there is a change in an .erb or .css file the browser will automatically refresh with the changes.

This is super-nice.

But we need to solve one more problem. With Tailwind, when you add classes to some HTML in a view or template, that class might not be in the generated tailwind.css file (./app/assets/builds/tailwind.css).

How do we update this file?

Easily:

> rails tailwindcss:build

Now, how do we get this to run automatically when any view or template (or even app/assets/stylesheets/application.tailwind.css) has been changed?

This is the next problem for me to solve.

I assume this is a solved-problem but me—being a Rails newbie—I’m still researching.

Anyone have any suggestions here?

P.S. I realize I might be “hyper-optimizing” workflow here. But I kinda got used to this kind of thing working on some other frameworks in the past: Make a change and it immediately shows in the browser. It felt like a game changer to me by making the “cost of change” super-small.

It looks like that to achieve what I want is as “simple” as running ./bin/dev vs. rails s:

And the ./Procfile looks like it might do what I want:

web: bin/rails server -p 3000
css: bin/rails tailwindcss:watch

However…

> ./bin/dev
Installing foreman...
Successfully installed foreman-0.87.2
Parsing documentation for foreman-0.87.2
Done installing documentation for foreman after 0 seconds
1 gem installed
./bin/dev: line 9: foreman: command not found

So a bit more digging.

SOLVED: Needed to add /usr/local/lib/ruby/gems/3.1.0/bin/ to my shell $PATH. Doh!