- Issue created by @NicholasS
- Merge request !30Fix bug where page caching was showing old view mode when content is revisited. β (Closed) created by NicholasS
- πΊπΈUnited States NicholasS
This does appear to fix the behavior I found, however I don't know the exact ramifications on caching performance. Seems to always run clear the cache now, so its almost like the page is now uncached.
So maybe a more experienced dev can find a better solution. But I guess this does validate an issue with page caching exists.
- πΊπΈUnited States NicholasS
Uploading a view of the behavior, along with showing how the current change appears to solve it.
- π©πͺGermany hctom
Hi NicholasS, thank you for your report.
Unfortunately I doubt that the View Mode Switch Field module is really the cause for this cache issue. It only uses core's
hook_entity_view_mode_alter()
hook and that one is called inEntityViewBuilder::getBuildDefaults()
BEFORE any caching happens. Because this field is a "normal" Field API field, its current value is always respected in the cache entry being build later, while saving an entity also always invalidates any cached entries already (e.g. seeEntityStorage::doPostSave()
and respectively::resetCache()
).I just tried to reproduce your issue with a vanilla Drupal install and the Basic page content type having a view mode switch field for the
Full
view mode, but with no luck. When I enable the cache debug inservices.yml
, I can even see in the rendered markup, that there are cache keys used, that vary between the original view mode and the view mode to switch to (which will result in different cache entries):View mode not switched
<!-- CACHE KEYS: * entity_view * node * 1 * full -->
View mode switched to
teaser
via View Mode Switch Field<!-- CACHE KEYS: * entity_view * node * 1 * teaser -->
In your video, the actually changing part of the node page is quite "far away" from the rest of your node (in the header above navigation and hero element), so I wanted to ask, if this is something you render programmatically or is the whole page created by your node template? I'm only asking, because if you render some parts programmatically, you have to make sure, that any of the node's cache tags/contexts/keys bubble up in the render pipeline and do not get lost, which in turn may result in caching issues.
Another thing that makes me wonder, is that e.g. node A should never change cache entries of node B.Can you please have a look at the cache debug values in your project or if there may be something else, that might interfere with Drupal core's caching mechanisms on these pages. And just another question: Does the display also change when you reload the switched node several times after it has been cached?
- πΊπΈUnited States NicholasS
Thanks for the fast reply.
so I wanted to ask, if this is something you render programmatically or is the whole page created by your node template?
Yeah sorry some missing details. The default view of my pages is the
page.html.twig
and when I change the view mode the page should be usingpage--page--no-headers-or-footers.html.twig
no-headers-or-footers being the name of the view mode. And yeah its just simple hardcoded HTML in that twig that sets a different header/footer.When I remove that cache clear I added, and I get that normal view mode when its not supposed to I see its using the default view mode.
<!-- THEME DEBUG --> <!-- THEME HOOK: 'page' --> <!-- FILE NAME SUGGESTIONS: * page--page--.html.twig x page--node--page.html.twig * page--node--72661.html.twig * page--node--%.html.twig x page--node--page.html.twig * page--node.html.twig *
Then I re-save the page and get the view mode suggestion.
<!-- THEME DEBUG --> <!-- THEME HOOK: 'page' --> <!-- FILE NAME SUGGESTIONS: x page--page--no-headers-or-footers.html.twig * page--node--page.html.twig * page--node--72661.html.twig * page--node--%.html.twig * page--node--page.html.twig * page--node.html.twig * page.html.twig -->
Let me dive into the cache debug in services.yml and report back with those findings.
- πΊπΈUnited States NicholasS
Ok I loaded up the page when it was the "default" view mode. Then saved the page which triggered the view mode switch, here is a diff of the cache markup
https://www.diffchecker.com/fNijtehK/The right side when it says "
<!-- CACHE-HIT: No -->" is when I see the view mode switch (no-headers-or-footers)
I'll attach a video too as there is alot more cache tag info hope I got the right ones you wanted.
- πΊπΈUnited States NicholasS
Does the display also change when you reload the switched node several times after it has been cached?
I only see the switched mode immediately after the node is saved. Refreshing a second time+ I see the default view mode continuously.
I will add in another part of the site we are using this module, to display a field in another view mode and it works correctly. I know my needs might be non-typical use of the field, as I want it to "bubble up" a change so to speak to affect the header, aka use a different twig template.
Maybe I am just miss-using the module? Love if it could help the my use case though! :D
- π©πͺGermany hctom
Thanks for the details. That definitely helps identifying the potential problem. I again tried to reproduce this with a vanilla Drupal 10.2.3 installation and I can see, that the following theme suggestion are custom ones maybe defined by some code or another module:
x page--page--no-headers-or-footers.html.twig * page--node--page.html.twig * page--node--72661.html.twig
Core's theme suggestions β are based on internal path only.
So maybe the custom code providing those new suggestions does either not have the correct view mode available or itself some caching issues?
- πΊπΈUnited States NicholasS
Awe thanks, ok yeah must be my theme suggestions. I see I have something like
function THEME_theme_suggestions_page_alter(array &$suggestions, array &$variables) { // Add suggestions for the page based off the node type and view mode $node = \Drupal::routeMatch()->getParameter('node'); if ($node) { $suggestions[] = 'page__' . $node->getType() . '__' . $node->current_view_mode; } }
and
function THEME_preprocess_node(array &$variables, $hook) { if (isset($variables['view_mode'])) { $node = $variables['node']; $node->current_view_mode = $variables['view_mode']; } }
I'll play with those, I guess when its cached those suggestions for some reason are not being fired.
- Status changed to Closed: works as designed
10 months ago 1:13pm 15 February 2024 - πΊπΈUnited States NicholasS
For anyone else who stumbles upon this and wants the solution.
Seems when the page is cached, there is no
$node->current_view_mode;
so I had to extract the view mode out of the cache tags to maintain the same theme suggestions as non-cached pages.function THEME_theme_suggestions_page_alter(array &$suggestions, array &$variables) { // Add suggestions for the page based off the node type and view mode $node = \Drupal::routeMatch()->getParameter('node'); if ($node) { // Get the nodes current view mode by extracting it from cacheTags()array 0:"config:core.entity_view_mode.node.preview" its the last part of the string $cacheTags = $node->getCacheTags(); // loop over cacheTags to find the view mode entity_view_mode and extract the view mode from the string foreach ($cacheTags as $cacheTag) { if (strpos($cacheTag, 'entity_view_mode') !== false) { $cache_node_view_mode = substr($cacheTag, strrpos($cacheTag, '.') + 1); } } $node_view_mode = $node->current_view_mode; // use either current_view_mode or the one from the cacheTags $node_current_view_mode = !empty($node_view_mode) ? $node_view_mode : $cache_node_view_mode; $suggestions[] = 'page__' . $node->getType() . '__' . $node_current_view_mode; } }
- π©πͺGermany hctom
Thank you for your feedback and I'm glad I was able to help.
...but I am not really sure about your fix ;) I'd be careful with this, because of the quite hacky parsing of the view mode and in addition: I think you will have to add something to vary your
page*.html.twig
render cache entries per used suggestion. Maybe it is even enough to add a view mode based cache key in ahook_preprocess_page()
implementation, but I am not really sure about this and would have to do some testing with this. Without this cache key Drupal may cache rendering ofpage.html.twig
with the same cache entry aspage--your-view-mode-based-suggestion.html.twig
... but as I already said: That would require a lot more testing and debugging to see what really happens there ;)