-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to invalidate the cache in JS? #352
Comments
If you remove the speculation rules from the page then this removes the pre-prerendred page. You can also re-prerender them by re-adding the speculation rules in a new task (or new microtask). Note this must be in a separate task (using A function like this can refresh all speculated pages and it could be called when add to basket is used: function RefreshPrerenders() {
const speculationScripts =
document.querySelectorAll('script[type="speculationrules"]');
for (speculationScript in speculationScripts) {
// Get the current rules as JSON text
const ruleSet = speculationScript.textContent;
// Remove the existing script to reset prerendering
speculationScript.remove();
// Create a new speculation rules script in a new task
// (to give the browser time to cancel the older speculation)
// Note: queueMicrotask also works here.
setTimeout( () => {
const newScript = document.createElement('script');
newScript.type = 'speculationrules';
newScript.textContent = ruleSet;
console.log(newScript);
// Append the new script back to the document
document.body.appendChild(newScript);
}, 0);
}
} A better pattern is to recheck current state on page activation and update. This will allow the previous prerender not to be wasted (or have to be re-prerendered). If this is also done on page visibility changes then it would also solve this problem for those of us that use multiple tabs even when prerender is not used. |
Thanks for the answer. This looks like a rather complex solution for something that should be simpler. Can’t we have something like document.invalidateSpeculation(optionalPath) ? |
Well that JS snippet is to remove and re-add all speculation rules so is a bit more than just invalidating it. To invalidate all you can just do: document.querySelectorAll('script[type="speculationrules"]').forEach(element => element.remove()); Which is a bit simpler than my snippet (but also a bit more destructive in that all rules will now no longer exist and so new speculations cannot be rerun). But not sure what exactly you mean by "invalidate"?
|
Yes, your third situation is what we are trying to do. So cancel all speculation but keep the rules and re trigger them based on the selected behavior. I've tried the snippet and it works as you said but it really feels a bit hacky and hardly discoverable (especially wrapping it around a setTimeout). I feel this use case is common enough (at least all e-commerce websites will need it) to deserve a cleaner API. |
Agreed. I'm working on a new post as we speak to document this and make this more well-known. Will let others here comment on the addition of a new API. As I say, I do agree this could be made more ergonomic, but not sure of the priority of this work. |
The ideal solution here is to keep your pages up to date while they're being prerendered, or rendered in a second tab, using solutions like Otherwise, removing the speculation rule is indeed the best solution. |
I was discussing with a Shopify engineer about this, as there are interest to have support of speculation rules in Shopify natively. Due to this invalidation issue though, their idea would be to use a conservative approach to limit the risk (but it would not completely eliminate it though), but after testing it, while this reduce the TTFB, it's near the nearly instant experience of more aggressive approach. What about allowing a response to return special HTTP headers indicating the browser to invalidate the cache? For instance,in Shopify context, the cache would need to be invalidated whenever the customer interact with the cart (so when a new line item is edited, removed or added). Shopify could eventually configure their server to make all those This would provide a clean way to handle this problem. And the browser could automatically invalidate the cache of all tabs sharing the same domain. |
It's worth considering, but my initial impression is that's a lot of complexity to add to the feature (now the server can control the speculation rules cache, separately from the HTTP cache!?). And it's just another way to do something that's already possible. Can you explain why the existing invalidation abilities are not possible for your site? |
I Will let Shopify clarify (ping @krzksz) but from what I understand Shopify would like to integrate this natively to all existing Shopify stores (a kind of platform level managed rules). Invalidation would happen whenever the user interacts with the cart (add a product to cart, remove a product to cart, edit an existing quantity…). Based on your approach, there would be two ways:
the response header approach brings a clean solution that would allow Shopify to deploy this and improving performance of millions on stores, without any drawback. E-commerce where speed is essential appears to be THE perfect use case of speculation rules, so not having a solution for that sounds to me like a major flaw in the speculation rules API design. |
I forgot to say, thanks for that detailed comment. What you explained makes sense. In general, we've found that it's worthwhile to add features to help balance the platform / individual website responsibilities, instead of requiring them to coordinate or interfere with each others' code. That's what's driven work on the We're considering extending the |
Thanks a lot for considering a solution to this problem. I've never heard of this header but this sounds like a nice idea. I think that we can start with a simple solution clearing all the speculation rules (after re-thinking it in context of Shopify for instance, I actually can't think of a use case where I would like to invalidate just a part of the rules; as adding to the cart can actually modify the HTML of every possible page). |
Issue triage: I have captured the ideas around clear-site-data in this new issue: #357. Let me close this issue, as we've departed a decent ways from the OP, so starting fresh there seems cleaner. But if people still believe JS control is a good idea, then we can reopen or create a separate issue. |
Thanks for moving on this. With this approach I don’t see any need for Javascript based invalidation :). |
Hello,
I am exploring speculation rules in context of a Shopify theme (e-commerce) and so far, I have had great success. Performance is really nice and most of the limitations I had with Instant.Page are fixed by this system.
However, similar to Instant.Page, I am facing an issue that is pretty common in e-commerce:
Due to that, the cart content / cart count will show the value before the product has been added to cart. Ideally, we would need a JavaScript API to allow invalidate all or part of the cache, that we could call when a product has been added to the cart, for instance.
For now, the only workaround I've found would be to add a flag to local storage when a product has been added to cart, and use the
document.prerendering
to force a reload of the page, but that's defeating a bit the purpose.Thanks.
The text was updated successfully, but these errors were encountered: