verbb / navigation

A Craft CMS plugin to create navigation menus for your site.
Other
90 stars 23 forks source link

Blitz Cache (Cached include) and active states #410

Closed svondervoort closed 2 hours ago

svondervoort commented 2 days ago

Question

We are using Blitz cache for our sites and would like to use the Cached include feature of Blitz Cache for the header navigation. This way when the navigation is changed Blitz Cache doesn't have to refresh all cached pages.

But the problem we're running into at the moment is that the active state doesn't seem to be working when including. Do we have to send specific parameters into the Cached include?

Since the active state of an item is done by the URL and Cached include is a different cal/URL that returns the template it never matches.

Additional context

No response

engram-design commented 1 day ago

Is this referring to the {{ craft.blitz.includeCached('_includes/call-to-action') }} functionality? I'm not 100% across that, but I can look into it.

But active state is a tricky one in that it can't really be cached, because it changes (potentially) on every page.

svondervoort commented 1 day ago

Yes thats correct. I am not entirely sure how it handles different versions of the same cached template, but my guess is it would do so by the params. So essentially every active state within the navigation is its own cached navigation partial.

The other option would be to use Dynamic Include, which does a similar request to an URL but return real-time HTML instead of cached HTML.

Just to clarify why we would like to cache the navigation separately: If the navigation is changed, Blitz will have to update all entries that have the navigation present. We think it is less demanding to regenerate the navigation cache then the full page cache.

Edit: Just found out there is the craft.navigation.getActiveNode() method which I might be able to put in the params.

So that part will be cached into the parent page which then includes (Cached or Dynamic) the navigation with the activeNode which I then can use in the active check within.

bencroker commented 1 day ago

If you have an active state in the navigation then you’ll end up with one cached version per possible active navigation item. So if you have 10 possible active states, you’re going to end up with up to 10 cached includes. That is probably still better than having to clear the cache for hundreds or thousands of pages each time the navigation is changed.

You’ll need to pass a parameter into the cached include template and get the Navigation plugin to use the param to determine the active state. For example:

// Using a node ID
{{ craft.blitz.includeCached(template, { activeNodeId: 1 }) }}

// Using a URI segment
{{ craft.blitz.includeCached(template, { segment: craft.app.request.segment(1) }) }}

// Using the URL
{{ craft.blitz.includeCached(template, { url: craft.app.request.url }) }}

https://putyourlightson.com/plugins/blitz#cached-includes

engram-design commented 1 day ago

Thanks for the insight @bencroker, I'll admit that I've yet to use this on a project, but will be giving it a spin shortly.

svondervoort commented 2 hours ago

I just did some testing and this seems to be working like a charm.

Since we have a nested navigation I use the following logic to check if an ancestor needs to be active as well:

{# layout.twig with the includeCached #}
{% set headerMainActiveNode = craft.navigation.getActiveNode('headerMain') %}
{# headerMain.twig - the includeCached template #}
{% set activeNodes = [] %}
{% if headerMainActiveNode is not empty %}
    {% set activeNodes = activeNodes | merge([headerMainActiveNode]) %}
    {% set activeNodes = activeNodes | merge(craft.navigation.nodes().ancestorOf(headerMainActiveNode).ids()) %}
{% endif %}
svondervoort commented 2 hours ago

Not sure if it is related or I should open a new issue for @bencroker but when I move one navigation item to another position, I see Blitz is refreshing the cache since it creates a Queue Job. But after I visit a page I don't immediately see the change and Blitz refreshes the cache for a second time. Then after reloading I do see the change.

Or is this because of the Refresh Mode set to Expire the cache, regenerate manually or organically*?

bencroker commented 2 hours ago

Yes, it is because of your refresh mode.

svondervoort commented 2 hours ago

But what does the first refresh do then, or why is it triggered? And why is visiting the page again triggering a second refresh of the cache?

I understand visiting the page triggers the cache generation because of the Refresh Mode. So I'm wondering what the first refresh is about when changing something in the CP.

bencroker commented 50 minutes ago

The first refresh marks cached pages as expired. The second regenerates the expired page in the background, while the stale version is served to the user (in a stale-while-revalidate fashion).

svondervoort commented 44 minutes ago

Ah, that makes sense. I'll have to have another look, maybe the queue jobs where called differently or are they both called: Blitz refreshing cache?

Op vr 22 nov 2024, 17:33 schreef Ben Croker @.***>:

The first refresh marks cached pages as expired. The second regenerates the expired page in the background, while the stale version is served to the user (in a stale-while-revalidate fashion).

— Reply to this email directly, view it on GitHub https://github.com/verbb/navigation/issues/410#issuecomment-2494165701, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABGUFTEBQ7T2MAC6DQ2YSZT2B5MGDAVCNFSM6AAAAABSD4RTDWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIOJUGE3DKNZQGE . You are receiving this because you modified the open/close state.Message ID: @.***>