Avoiding Zeitwerk reload when views change

We’re replacing Webpacker with Vite in our Rails 7.1 application, and Vite has this plugin where it reloads the page when views are updated. The backend request to that page takes more than 1s, because classes are reloaded as well (as opposed to 200ms it takes when nothing has changed), which doesn’t provide as snappy autoreload experience as I would like.

Zeitwerk reloading is triggered because ActionView::CacheExpiry::ViewReloader reports that views were updated, and my understanding is that reloading is global – if any reloader reports that it’s been updated, everything is reloaded. If in Rails::Application::Finisher I make the following change:

app.reloader.check = lambda do
  app.reloaders
    .grep_v(ActionView::CacheExpiry::ViewReloader)
    .map(&:updated?).any?
end

The page reload is snappy, but then the view content doesn’t get updated, I still see the old version (duh) :smiley:

I was wondering if there have been considerations to make the reloading more granular in Rails, where it only reloads what it needs to. In this case, Zeitwerk ignores the app/views directory, so changes to views shouldn’t really require classes to be reloaded. Though I suppose it’s possible to modify classes inside view templates.

1 Like

We’ve talked a bit about this with @jhawthorn.

Historically, it seems it was done this way to leverage the existing concurrency mechanisms that prevent reloaders from being triggered in the middle of a request. However, this could be more fine-grained, just as you suggested.

1 Like