Skip to content

Move custom active trail detection to client-side JavaScript - #831

Merged
jjroelofs merged 5 commits into
8.xfrom
jur/8.x/827-menu-cache-improvement
Jul 8, 2026
Merged

Move custom active trail detection to client-side JavaScript#831
jjroelofs merged 5 commits into
8.xfrom
jur/8.x/827-menu-cache-improvement

Conversation

@jjroelofs

@jjroelofs jjroelofs commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Linked issues

Solution

Remove the custom server-side active trail workaround that added url.path cache context to every menu render (causing the menu to be cached per-URL-path). Replace with a lightweight client-side JavaScript that detects the active trail by comparing menu link hrefs against the current URL. Core's built-in in_active_trail continues to work for standard menu links; the JS covers edge cases like Views-generated menu links (core issue #3359511).

This removes the extra url.path cache variation that dxpr_theme was adding. Core's route.menu_active_trails:main cache context remains on menu blocks, so the menu still varies by active trail (not by every URL path). This significantly reduces the number of cached menu renders: from one per URL to roughly one per distinct active trail.

Checklist

  • I have read the CONTRIBUTING.md document.
  • My commit messages follow the contributing standards and style of this project.
  • My code follows the coding standards and style of this project.
  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to change).
  • Need to run update.php after code changes.
  • Requires a change to end-user documentation.
  • Requires a change to developer documentation.
  • Requires a change to QA tests.
  • Requires a new QA test.
  • I have updated the documentation accordingly.
  • All new and existing tests passed.

jjroelofs added 3 commits July 8, 2026 07:30
Remove the server-side active trail workaround that added url.path
cache context to every menu render, causing the menu block to be
cached per URL path. Replace with a lightweight client-side JavaScript
that detects the active trail by comparing menu link hrefs against the
current URL pathname.

Core's built-in in_active_trail continues to work for standard menu
links; the JS covers edge cases like Views-generated menu links
(core issue #3359511).

Fixes #827
@jjroelofs

Copy link
Copy Markdown
Collaborator Author

Review findings:

  1. dxpr_theme.theme:294 - This keeps the client-side visual state, but it does not disable Drupal core's own active-trail calculation/cache context for the main menu block. config/optional/block.block.dxpr_theme_main_menu.yml still has no settings.ignore_active_trail: true, so on Drupal 11.4+ SystemMenuBlock will continue computing in_active_trail and varying by route.menu_active_trails:main. That means the server-rendered menu still is not the same markup on every page, which is the main cacheability goal of Refactoring: improve menu block render cacheability #827. Can we either enable that block setting where supported, with an update path for existing installs if needed, or narrow the PR/docs to say this only removes the extra url.path variation?

  2. js/dist/dxpr-theme-active-trail.js:20 - link.pathname drops the origin, so an external menu link like https://example.org/about will be marked active when the current site is on /about. The previous PHP comparison would not match external URLs against the local path. Please parse the href with new URL(link.href) and require url.origin === window.location.origin before comparing pathnames.

Checks: npx eslint js/dist/dxpr-theme-active-trail.js passed locally, and GitHub checks are green. Local ./vendor/bin/phpcs is unavailable in this checkout.

I tried to submit this as a formal request-changes review, but GitHub does not allow the PR author account to request changes on its own PR.

Skip external links in client-side active trail detection by checking
origin before comparing pathnames. Fix @deprecated version to 8.2.0
since the theme is already past 8.x. Clarify scope: this PR removes
the url.path cache context, not the core active trail cache context.
@jjroelofs

Copy link
Copy Markdown
Collaborator Author

Follow-up after dd51a0e:

  • The external URL false positive is fixed. Thanks.
  • The PHP docblock now correctly says this removes the extra url.path context while core route.menu_active_trails remains. The PR description still says the server-rendered menu is "identical regardless of the current page path", though, so that should be updated to match the narrower scope.
  • One smaller JS edge case remains: hash-only links such as href="#" still resolve to the current page URL, so they will be marked active on every page because only pathname is compared. That can affect dropdown placeholder links/custom anchors. Please skip hash-only hrefs before the pathname comparison, e.g. by checking the raw href attribute.

Links with href="#" resolve to the current page URL, causing them
to be falsely marked active on every page. Check the raw href
attribute and skip fragment-only values before pathname comparison.
@jjroelofs
jjroelofs merged commit ccc7555 into 8.x Jul 8, 2026
5 checks passed
@jjroelofs
jjroelofs deleted the jur/8.x/827-menu-cache-improvement branch July 8, 2026 09:28
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.

Refactoring: improve menu block render cacheability

1 participant