Contextual links template won't re-render due to cache issues

Created on 18 August 2023, 11 months ago
Updated 7 May 2024, about 2 months ago

Problem/Motivation

Contextual link template (links.html.twig or links--contextual.html.twig) gets cached at the first hit (render) of each contextual link and render cache won't get invalidated via the usual methods (disabling twig render cache, drush cr, setting caches to cache.backend.null on settings.local.php, etc)

This means that:

  1. Themers can't see the changes made on links.html.twig or similar templates that affect the contextual links. Regular cache clearing methods won't work. The only way seems to be manually remove the populated entries from window.sessionStorage in order to force a re-render via AJAX
  2. We can run on caching issues such as: use THEME1 to visit your page, switch to THEME2 and the template from THEME1 will still be used to render the links

Steps to reproduce

  1. Create a new Drupal 10.1.x site.
  2. Create a new theme. I've used starterkit: php web/core/scripts/drupal generate-theme poc. Important! Don't use Olivero I don't know why but this won't work on Olivero as it seems to bypass the link theme hook and template (?).
  3. Enable the new theme. It is recommended to enable twig debugging and disable twig caches.
  4. Go to the front page, check that the contextual links are rendered using links.html.twig, like this:
  5. Edit the theme links.html.twig file, clear caches, revisit the page and check that the changes haven't been applied. You should be able to see the changes on other, different uses of link.html.twig, such as in the toolbar shortcuts.
  6. You can also try to add the template suggestion links--contextual.html.twig to your theme. It won't be applied.
  7. You can also try running window.sessionStorage.clear() on the console. This will clear all cached render results, trigger a new AJAX request and then you will be able to see your template changes.

Proposed resolution

Since contextual links are rendered using Drupal's theming layer, render/twig cache invalidation should affect the contextual links.

As it is right now, it seems only changes on user permissions trigger a re-render of the caches:

  // Clear the cached contextual links whenever the current user's set of
  // permissions changes.
  const cachedPermissionsHash = storage.getItem(
    'Drupal.contextual.permissionsHash',
  );
  const permissionsHash = drupalSettings.user.permissionsHash;
  if (cachedPermissionsHash !== permissionsHash) {
    if (typeof permissionsHash === 'string') {
      _.chain(storage)
        .keys()
        .each((key) => {
          if (key.substring(0, 18) === 'Drupal.contextual.') {
            storage.removeItem(key);
          }
        });
    }
    storage.setItem('Drupal.contextual.permissionsHash', permissionsHash);
  }

This can lead to great problems. In my case, I had a typo on links.html.twig that, after being rendered and cached by contextual links, resulted on a clearly visible visual bug that I couldn't get rid of.

Another solution could be disallowing themers to alter the contextual links, this is, avoid using a theme hook that will result on a template and a suggestion being printed on twig debug and available to themers (such as Olivero does, I don't know how).

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component
ContextualΒ  β†’

Last updated 2 days ago

Created by

πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Issue created by @idiaz.roncero
  • Status changed to Closed: cannot reproduce 10 months ago
  • πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

    It seems I had something wrong on my side, even if I had a clean D10 install. maybe something with my local development environment? Nevertheless, it's working OK now.

    Closing as can't reproduce.

  • Status changed to Active 10 months ago
  • πŸ‡ͺπŸ‡ΈSpain idiaz.roncero Madrid

    Re-opening this issue as it has happened again, on a completely different environment and under a completely different set of circumstances.

    First time it happened to me, I was using a clean D10 install, no modules installed (other than the standard profile ones) on a DDEV local env.

    This time it was an old project (7 years old), on D10, with a lot of active modules and a lot of customizations on a Docker4Drupal local env.

    I uninstalled the module layout_builder_iframe_modal, which alters the contextual links on Layout Builder blocks.

    Then, I found the same error as reported above: the contextual links remained cached, with the layout_builder_iframe_modal alterations, leading to errors as it changes the data-dialog-type attribute.

    Only manually cleaning the cache by using window.sessionStorage.clear() on the console solved the issue. No amount of Drupal cache clears resolved the issue.

    I still don't know under which circumstances the error appears, but the fact that I have reproduce it on two completely different environments leads me to consider that this might affect more people.

  • πŸ‡§πŸ‡ͺBelgium weseze

    Also experienced this issue today.
    Frontend had added classes/wrappers to the links.html.twig and written CSS for it, nothing was visible...
    We then tried removing the twig and noticed it was still in use...

    Running "window.sessionStorage.clear()" fixed it.

  • πŸ‡ΊπŸ‡ΈUnited States BrightBold Boston, MA

    Thank you for the window.sessionStorage.clear() tip! I spent two days trying to figure out why contextual link lis weren't populating; of course the logical source was my subtheme, but there was no pattern to when and where it appeared. As I was able to reproduce it in the base theme, Olivero, and Claro, I became increasingly confused about the source of the problem. Learning that normal cache clearing wouldn't work and that I needed window.sessionStorage.clear() instead allowed me to successfully track down the culprit. So grateful for this thorough bug report!

Production build 0.69.0 2024