Skip to content

Only recompile components when a template changed, instead of before every request - #2730

Open
czj wants to merge 1 commit into
ViewComponent:mainfrom
czj:compile-cache-template-watcher
Open

czj wants to merge 1 commit into
ViewComponent:mainfrom
czj:compile-cache-template-watcher

Conversation

@czj

@czj czj commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2729

What are you trying to accomplish?

When templates aren't cached, which is the default in development, the engine empties the compile cache before every request, so every request recompiles every component it renders, even when no template changed. This only invalidates the cache when a template or a translation file was added, changed, or removed.

On our app (between 43 and 60 components per page), median of 7 requests after a warm-up:

Page Before After
Home 261 ms 160 ms
Category 148 ms 71 ms
Product 217 ms 106 ms
Brand 166 ms 83 ms

What approach did you choose and why?

The same one as Action View's ActionView::CacheExpiry::ViewReloader for views: a config.file_watcher over the autoload paths, since components can live outside app/components and in engines, watching ActionView::Template::Handlers.extensions plus yml and yaml for sidecar translations. Changes to Ruby files, inline templates included, already reload the application, so the cache is also cleared on before_class_unload.

The watcher is built on the first request that doesn't cache templates, so the template handlers registered by gems like Slim or Haml are known by then, and ActionView::Base.cache_template_loading is still checked on every request, as the test helpers toggle it.

Anything you want to highlight for special attention from reviewers?

The existing tests for template changes being reflected on the next request fail if the watcher doesn't invalidate the cache, so they cover the change. I added one checking that a component isn't recompiled when no template changed, which fails on main, and one for an added template.

When templates aren't cached, the engine emptied the compile cache
before every request, so every request recompiled every component it
rendered, even when nothing changed.

Like Action View does for views, watch the templates and translation
files in the autoload paths with config.file_watcher, and only
invalidate the cache when one of them is added, changed, or removed.
Changes to Ruby files reload the application, which clears the cache.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Only recompile components when a template changed, instead of before every request

1 participant