-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Remove nocache headers from Cart page to enable bfcache (instant back/forward navigations) #58445
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
Remove nocache headers from Cart page to enable bfcache (instant back/forward navigations) #58445
Conversation
The pages for Checkout and My Account might also be suitable for this change, but I didn't test that they have |
Thank you for this PR @westonruter, our perops team was looking into those headers and actually looking to add them to more pages, I will bring them to the discussion. |
@senadir Adding |
not more pages, just the whole cart/checkout pages, as we aggressively cache other pages and we don't want to do that for cart/checkout. |
Oh good. So in other words, in addition to removing
|
Removing the Chrome-specific stuff seems ok - and I particularly support the idea of preserving core's cache-control directives, especially "private". But this will remove the "no-cache" directive for all visitors on the cart page. There are likely thousands of WooCommerce sites behind edge caches which rely on those headers to prevent caching shopping carts across users. I think it would be better to add "private" to cache-control on cart and checkout pages instead of no-cache. |
@thingalon By This PR removes Core added the |
@westonruter - this diff affects both the On a fresh temp WordPress / WooCommerce install:
With the patch installed:
The diff prevents I think it'd be more appropriate to set Thinking on it further: this will also bypass calling |
@thingalon Oh yes, you're right. I confused myself because I also have in mind removing Update: See https://core.trac.wordpress.org/ticket/63636 So yes, |
…to remove/cart-page-cache-control-no-store
📝 Walkthrough""" WalkthroughThe caching prevention logic in WooCommerce was refactored by removing the old Changes
Sequence Diagram(s)sequenceDiagram
participant WP as WordPress
participant WC as WC_Cache_Helper
WP->>WC: Apply wp_headers filter (with $headers)
WC->>WC: Check if WooCommerce page (cart, checkout, my account)
alt If WooCommerce page
WC->>WC: Define no-cache constants
WC->>WC: Merge cache-control directives (private, no-cache, must-revalidate, max-age=0) into $headers (exclude no-store)
else Not WooCommerce page
WC->>WC: Return $headers unchanged
end
WC->>WP: Return modified $headers
Poem
""" 📜 Recent review detailsConfiguration used: .coderabbit.yml 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
@thingalon OK, how about 3d0d954?
In the authenticated state, the The |
@westonruter - that looks good to me, and seems like a clear improvement around caching headers. Thanks for working on this! @senadir - can you please review it for merging into WooCommerce? :) |
Here's a demo of the impact. While not being logged-in to WordPress and emulating a Slow 4G connection, compare entering a coupon on the cart page, then navigating to the shop, and then going back to the cart page. Notice how much faster the experience is when bfcache is enabled, and notice that the coupon dropdown retains its open state with the unsubmitted coupon still populating the field:
Granted, the speed effect is exaggerated here because I had DevTools open with cache disabled, besides emulating Slow 4G. |
Testing GuidelinesHi , Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed. Reminder: PR reviewers are required to document testing performed. This includes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good to me, I left a couple of comments, one of them is slightly blocking unless you have which is about not using wp_get_nocache_headers
if we're not longer hooking into nocache_headers
filter.
*/ | ||
public static function additional_nocache_headers( $headers ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the changes, I'm a bit hesitant about deleting this public function outright but I can't see any usage for it publicly so I think we're good to go.
// These directives are all included in `wp_get_nocache_headers()`, with the exclusion of `no-store` for the sake of bfcache. | ||
$new_directives = array( | ||
// Prevent caching the response in reverse proxies. | ||
'private', | ||
|
||
// Ensure freshness of the response but without `no-store` so that bfcache won't be disabled. | ||
'no-cache', | ||
'must-revalidate', | ||
'max-age=0', | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why not use wp_get_nocache_headers
and remove no-store
from it instead of maintaining our own list here? that function also benefit from having a filter built-in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that makes sense.
How about this: we merge the headers from wp_get_nocache_headers()
into $headers
, and then if the user is not logged-in, we also remove no-store
from Cache-Control
. Then when https://core.trac.wordpress.org/ticket/63636 lands in core (hopefully) the no-store
directive will also be removed for logged-in users automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to go with that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See 47f9b9c
|
||
if ( $set_cache ) { | ||
$headers['Cache-Control'] = 'no-transform, no-cache, no-store, must-revalidate'; | ||
} | ||
return $headers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR discussion mentioned adding back no-store
for authenticated users, at which point are we doing that because I can't seem to see it? unless you're assuming being on cart/checkout/my-account equal being authenticated? which is technically true but doesn't cover all cases of being authenticated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding no-store
or removing the directive?
Are you referring to this comment?
In https://core.trac.wordpress.org/ticket/63636 I'm working on removing no-store
for authenticated users in core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was about this comment that includes no-store
for authed users
@westonruter I'm going on sabbatical by the end of this week; I'd love if we could get this merged ASAP so I don't need to hand it over. Let me know if you need help applying feedback. |
I will try to amend the PR tomorrow morning to do so, but I'll be AFK for the rest of the week. |
…to remove/cart-page-cache-control-no-store
Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good, thank you @westonruter
I've opened a similar pull request for Jetpack: Automattic/jetpack#44322 |
Changes proposed in this Pull Request:
I found that nocache headers were being sent on the Cart page seemingly unnecessarily. This appears to have been done for the sake of the browser's back/forward cache (bfcache) holding onto a stale cart page which wouldn't reflect a change made from another page after hitting the back button. However, as can be seen in the current version of Chrome, this no longer seems to be the case. (See screen recording below.)
In particular, this is no longer necessary because there is a
pageshow
event listener running on the Cart page to update the cart whenever landing on the cart after a bfcache navigation. For example:woocommerce/plugins/woocommerce/client/legacy/js/frontend/cart-fragments.js
Lines 109 to 115 in 4697b87
This PR therefore improves performance of navigating to and from the cart page by allowing the page to be served from bfcache.
Finally, this PR ensures the original
Cache-Control
directives fromnocache_headers()
are preserved when additional nocache headers are set. Namely, in WP core changeset r55968 the use ofprivate
was introduced.This includes a commit (33c6961) from #58444 to remove the obsolete Google Web Light support. Once that PR is merged, that change will be removed from this PR.
Screenshots or screen recordings:
Screen.Recording.2025-05-31.at.17.16.58.mov
How to test the changes in this Pull Request:
Cache-Control: no-store
is currently sent for authenticated users).Changelog entry
Changelog Entry Details
Significance
Type
Message
Remove nocache headers from Cart page to enable bfcache
Changelog Entry Comment
Comment