Personally, I never used live reloading in Rails apps apart from the one that comes with webpacker
gem. But things changed when I started working on embedded Shopify apps. They’re loaded as an iframe inside the Shopify admin panel. And reloading parent page + iframe together is pretty slow. This made editing views, CSS, or JS pretty painful 😞. To see the results of my changes I have to wait for 4-5s for browser to reload the page. At this point, I started to think that there should be a better way and started exploring live reloading.
Usually, live reloading is done by fully reloading browser page via location.reload();
. But this wasn’t sufficient for my use case. I wanted to only update page content without doing a full page reload. Luckily my apps were built with Hotwire Turbo. And Turbo
already knows how to reload only the content inside body
without reloading the whole page. All I needed to do is to teach Turbo
how to reload the current page when app’s view, CSS, or JS files are changed.
This is how Hotwire::Livereload gem was born. I created a simple Rails engine that uses listen
gem to track changes in app files and sends reload requests to Turbo
via ActionCable
when files are changed. As a result, we get very fast live reloading without a full browser refresh. Exactly what I was needed.
Getting started
To start using Hotwire::Livereload add it to Gemfile:
bundle add hotwire-livereload --group development
And run installer:
rails livereload:install
That’s basically it! By default the gem will listen for changes in the following folders:
- app/views
- app/helpers
- app/javascript
- app/assets/stylesheets
- app/assets/javascripts
- app/assets/images
- app/components
- config/locales
This covers the most common use cases. But you can tweak it with configuration if needed.
Configuration
To listen for custom folder add:
# config/environments/development.rb
Rails.application.configure do
# ...
config.hotwire_livereload.listen_paths << Rails.root.join("app/custom_folder")
end
If you don’t have data-turbo-track="reload"
attribute on your JS and CSS bundles you might need to setup force reloading. This will trigger full browser reloading for JS and CSS files only:
# config/environments/development.rb
Rails.application.configure do
# ...
config.hotwire_livereload.force_reload_paths << Rails.root.join("app/assets/stylesheets")
config.hotwire_livereload.force_reload_paths << Rails.root.join("app/javascript")
end
Disable livereload
In case if you want to disable live reloading temporarily you can do it using the following rake task:
bin/rails livereload:disable
This will create tmp/livereload-disabled.txt
file and will stop live reloading immediately. No server restart is required. To enable it again run:
bin/rails livereload:enable
Wrapping up
Live reloading is a very handy tool for modern web app development. I found it especially useful for Rails apps with TailwindCSS and for embedded Shopify apps. And Hotwire::Livereload gem makes it very easy to setup live reloading for Hotwire Rails apps. I will use it in all of my Rails apps moving forward. And I hope you’ll find it useful too.
If want to hear more from me follow me on Twitter. I tweet about my journey of building and growing Shopify apps using Ruby on Rails, Hotwire, and Polaris ViewComponents.