Skip to content

Enable caching support for all components by default - #2720

Open
joelhawksley wants to merge 10 commits into
mainfrom
joelhawksley-caching-pr-strategy
Open

joelhawksley wants to merge 10 commits into
mainfrom
joelhawksley-caching-pr-strategy

Conversation

@joelhawksley

@joelhawksley joelhawksley commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

What are you trying to accomplish?

Enable caching support for all ViewComponents by default. Every component is integrated into Rails' template digest tree and can declare cache_on without including a module. ViewComponent::ExperimentallyCacheable is renamed to ViewComponent::Cacheable. The old name is removed without an alias, so existing include ViewComponent::ExperimentallyCacheable lines must be removed. Caching is no longer marked experimental in the guide or API docs. No module include or application-level opt-in is required for source dependency tracking, .cache_digest, digest-aware cache blocks inside component templates, or self-caching via cache_on.

This consolidates and supersedes #2711 and #2713, building on Erik Axel Nielsen's fixes for silently incomplete cache digests. The scope was subsequently expanded to make digest tracking automatic for every component, eliminating the application-wide activation side effect of including ExperimentallyCacheable on an unrelated component.

What approach did you choose and why?

  • Install Action View dependency tracking and the synthetic resolver during engine initialization, without checking whether any component opted in.
  • Register component subclasses from ViewComponent::Base and share registration for literal renders and explicit # Template Dependency: declarations. Store actual class names and virtual paths rather than reconstructing names with camelize, preserving acronym names and custom paths without retaining stale class objects across reloads.
  • Move .cache_digest and component-template fragment digest integration to ViewComponent::Base. Direct digest computation also registers the component, including any overridden virtual path.
  • Prepend Cacheable into ViewComponent::Base, so cache_on is available on every component. Explicit include ViewComponent::Cacheable is a harmless no-op (ActiveSupport::Concern skips modules already in the ancestor chain). Components still only cache their own output when they declare cache_on.
  • Remove the now-meaningless __vc_cacheable? predicate.
  • Preserve unexpected digest-error propagation from Raise errors while computing cache digests #2712. Dynamic renders still require explicit declarations, and partials continue using Rails' digest behavior.

This intentionally changes the default for all applications: existing Rails fragment cache blocks involving components now include component source dependencies, and every component responds to cache_on/cache_key. Components without fragment blocks or cache_on do not start caching output.

Anything you want to highlight for special attention from reviewers?

Regression coverage includes template and Ruby dependencies without caching opt-in, explicit declarations, transitive invalidation through a child with a custom virtual path to an acronym-named grandchild, actual fragment output after source changes, discovery starting from an empty registry, direct digest computation without prior registration, and autoload error propagation.

Component-hosted fragment fixtures no longer include the caching module, so existing exact-key, inherited-template, invalidation, and partial fall-through tests now exercise automatic behavior. The view fragment fixture renders only components without caching opt-in.

The sandbox's Zeitwerk inflector maps http_untracked_component to HTTPUntrackedComponent without changing Active Support's global inflections, exercising names that cannot be recovered with path.camelize.

Validation:

  • Full default suite: 662 Minitests, 5 engine compatibility tests, and 8 RSpec examples, all passing.
  • Rails 7.1 caching suites: 99 tests / 218 assertions, all passing.
  • Full StandardRB, ERB lint, caching guide prose lint, and git diff --check pass.
  • Fresh minimal Rails application with no caching opt-in installs both tracking hooks and computes a plain component's digest.
  • Regenerated public API documentation for .cache_digest.

Erik is credited as a co-author for the original proposals and regression coverage.

Consolidate the fixes proposed in #2711 and #2713. Register literal and declared dependencies by their actual class names and virtual paths, preserving acronym names, custom paths, and transitive invalidation without enabling output caching or suppressing digest errors.

Co-authored-by: Erik Axel Nielsen <erikaxel@lucalabs.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62a65b38-1933-46c3-aa8b-de40801e2c7f
joelhawksley and others added 4 commits October 9, 2026 12:16
Split the guide sentence flagged by Vale, remove directives for a Rails cop not loaded by StandardRB, and remove a redundant line continuation rejected by current RuboCop.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62a65b38-1933-46c3-aa8b-de40801e2c7f
Install digest discovery at engine initialization and move component digest APIs and fragment key integration to Base. Track every component automatically while keeping cache_on output caching opt-in.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62a65b38-1933-46c3-aa8b-de40801e2c7f
@joelhawksley joelhawksley changed the title Track discovered component dependencies without per-component caching opt-in Automatically track source digests for all components Oct 15, 2026
joelhawksley and others added 2 commits October 15, 2026 12:08
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62a65b38-1933-46c3-aa8b-de40801e2c7f
Prepend ViewComponent::ExperimentallyCacheable into ViewComponent::Base so
every component can declare cache_on without including the module.
Explicit includes remain harmless no-ops. Components still only cache
their own output when they declare cache_on.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5ebc5d1-5db1-4685-b58b-8efb26828c46
@joelhawksley joelhawksley changed the title Automatically track source digests for all components Enable caching support for all components by default Oct 19, 2026
joelhawksley and others added 3 commits October 19, 2026 13:53
Keep ViewComponent::ExperimentallyCacheable as a deprecated alias until
v5.0.0.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5ebc5d1-5db1-4685-b58b-8efb26828c46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5ebc5d1-5db1-4685-b58b-8efb26828c46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5ebc5d1-5db1-4685-b58b-8efb26828c46

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.

1 participant