I'm upgrading an old Rails 5/6 project (which includes some react components) to Rails 7 and replacing webpacker with esbuild. I managed to get everything working except livereload is only partially working, for both css and js.
Problem
I make a trivial change to background: #f00 !important; in application.scss (or a react component) and my rails server detects it
Rendered C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/hotwire-livereload-1.2.3/app/views/hotwire/livereload/_turbo_stream.html.erb (Duration: 0.3ms | Allocations: 83)
[ActionCable] Broadcasting to hotwire-livereload: "<turbo-stream action=\"replace\" target=\"hotwire-livereload\"><template><div id=\"hotwire-livereload\" data-changed=\"[".../app/assets/stylesheets/application.scss"]\"></div>\n</template></turbo-stream>"
Turbo::StreamsChannel transmitting "<turbo-stream action=\"replace\" target=\"hotwire-livereload\"><template><div id=\"hotwire-livereload\" data-changed=\"[".../app/assets/stylesheets/application.scss"]\"></div>\n</template></turbo-stream>" (via streamed from hotwire-livereload)
Started GET ...
Rendered C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/hotwire-livereload-1.2.3/app/views/hotwire/livereload/_head_turbo_stream.html.erb (Duration: 2.3ms | Allocations: 1102)
...
Completed 200 OK in 2251ms (Views: 2100.6ms | ActiveRecord: 67.2ms | Allocations: 899456)
Unsubscribing from channel: {"channel":"Turbo::StreamsChannel","signed_stream_name":"..."}
Turbo::StreamsChannel stopped streaming from hotwire-livereload
Turbo::StreamsChannel is transmitting the subscription confirmation
Turbo::StreamsChannel is streaming from hotwire-livereload
Client receiving the update:
[Hotwire::Livereload] Files changed. Reloading..
The page reloads, but the change I made to application.scss doesn't actually appear on the page. The change I made only appears after I refresh the page manually (F5). The same is true for both changes to CSS and JS. Happens in both Firefox and Chrome. No console errors.
Also, strange that the entire page would be re-rendered, when in fact all I changed was a simple css style.
What is going on?
Configuration
- Added the gems
jsbundling-rails,stimulus-rails,turbo-rails,hotwire-livereload,cssbundling-rails,redis rails livereload:install- Cleaned up old webpacker files and related webpacker packages, removed
react-rails(replaced with stimulus) - Added to
config/development.rb
config.hotwire_livereload.disable_default_listeners = true
config.hotwire_livereload.listen_paths << Rails.root.join("app/assets/builds")
config.hotwire_livereload.listen_paths << Rails.root.join("app/assets/stylesheets")
config.hotwire_livereload.reload_method = :turbo_stream
application.html.erb(note thejavascript_include_tag 'application': this is some legacy JS inapp/assets/javascriptswhich I am specifically omitting fromhotwire_livereloadand esbuild.
<%= stylesheet_link_tag 'application', "data-turbo-track": "reload" %>
<%= javascript_include_tag 'application', "data-turbo-track": "reload", defer: true %>
<%= javascript_include_tag 'react', "data-turbo-track": "reload", defer: true %>
<%= action_cable_meta_tag %>
<%= hotwire_livereload_tags if Rails.env.development? %>
- Using
esbuild-serveand aesbuild.config.jslike
import esbuildServe from 'esbuild-serve';
esbuildServe(
{
logLevel: "info",
entryPoints: ["app/javascript/react.js"],
bundle: true,
sourcemap: true,
outdir: "app/assets/builds",
publicPath: "assets",
loader:{".js":"jsx"},
define:{"process.env.NODE_ENV": "\"development\""},
minify: true
},
{
// serve options (optional)
port: 7000,
root: '.'
}
);
"scripts": {
"start": "node esbuild.config.js -w",
"build": "node esbuild.config.js",
"build:css": "sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules"
},