Kirill Platonov
Kirill Platonov
Jan 9, 2022

Live reloading for Hotwire Rails apps

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.