Beginning with WooCommerce 7.8, we implemented a change that disables the cart fragments script from being enqueued on all page routes of a WooCommerce store by default. Responsible for updating the cart widget after a successful add-to-cart event, the script can cause performance issues on stores not using that functionality. Going forward the script will now only be enqueued if the Cart Widget is rendered in a view. Keep in mind that some themes (like Storefront) hard-code the widget into the theme’s templates so it is not always user-added.
This article provides a deeper overview of why this change was necessary and some suggested best practices (or recommendations) going forward.
What is the get_refreshed_fragments
API or “cart fragments”?
WooCommerce cart fragments is a script that uses the WordPress admin-ajax API to update the cart without refreshing the page. The term get_refreshed_fragments
refers to the handle the AJAX request is registered to as well as the callback that is invoked by the AJAX request triggered whenever there is a change to the Cart on the front end of the store (or on regular intervals).
If you look at the cart-fragments.js
file, you can search for the string get_refreshed_fragments
and discover that there are a few places where this script is invoked:
- When the
wc_fragment_refresh
orupdated_wc_div
custom jQuery events are triggered. The legacy cart script uses this event. - A day in milliseconds after the cart is refreshed. This helps keep left-open tabs from going stale if the shopper has multiple tabs open while they are shopping. The day in milliseconds timeout for invoking the refreshing of the cart is also set on initial page load.
- When a page is shown after the browser button/action is used. This is mostly a fix addressing a quirk with Safari’s behaviour of aggressively caching views in browser history.
- There’s also some special handling for invoking in the context of the WordPress customizer.
As you can see, there are a number of places where this AJAX call is invoked by the cart fragments
script to keep the mini cart widget up to date.
Addressing Performance Issues
Prior to the change introduced in WooCommerce 7.8, the cart fragments script was enqueued on every page load in a WooCommerce even if the mini-cart widget wasn’t present on the page. This was less than ideal leading to unnecessary additional AJAX requests to the server. On heavily trafficked stores, this could severely impact the load on the server and the responsiveness of a site.
With the changes applied via WooCommerce 7.8, this impact is minimized to pages that have the Cart widget active, when third party scripts register cart-fragments
as a dependency, or when explicitly enqueued in code. We’re still investigating safe ways we can reduce this performance hit for usage of cart-fragments
across all stores while preserving backward compatibility but in the meantime, here are some suggested best practices for further reducing the impact of using this API.
Limit Cart Sync functionality to specific WooCommerce pages
Using the snippet below, you can limit the execution of the cart-fragments
script to specific pages. Note, the cart-fragments.js
file will still load, however, it won’t execute:
add_filter( 'woocommerce_get_script_data', function( $script_data, $handle ) { if ( 'wc-cart-fragments' === $handle ) { if ( is_woocommerce() || is_cart() || is_checkout() ) { return $script_data; } return null; } return $script_data; }, 10, 2 );
Caveats:
- If you have non-standard custom pages that have cart behaviour not satisfying the conditions for
is_woocommerce()
, the mini-cart widget won’t update as expected. - If you expose the mini-cart widget on every page of your site and also have server/page caching enabled for your store, it’s likely the mini-cart widget will not update to show the active cart contents for the shopper session on those cached pages.
Replace usage of the Mini-Cart Widget with the Mini-Cart Block
The Mini-Cart block has a number of built-in performance measures to optimize the scalability of the live cart functionality and does not use the cart fragments API. As a result, we definitely recommend developers of themes and plugins switch to using and implementing the Mini-Cart block for this functionality.
For block themes
If the store is using a block theme, this is as easy as either using one of the available WooCommerce header patterns from WooCommerce core as a replacement for the current theme’s header template part content or adding the Mini-Cart block to your theme’s active header template part.
For classic themes with widget areas
If your classic theme does not hard code the Mini-Cart widget in the theme file, and instead implements it via a widget area, you can replace the Mini-Cart widget with the Mini-Cart block.
For classic themes with hardcoded mini-cart widget use.
The good news is that it’s possible to programmatically inject the Mini-Cart block into your theme to replace the Mini-Cart widget. While we’re still internally discussing our approach to rolling this out, I’ve done a proof of concept pull request for the Storefront classic theme that demonstrates replacing the Mini-Cart widget with the Mini-Cart block.
Note, implementing something like this for a classic theme also exposes to users (via add_theme_support( ‘block-template-parts’ )
) the ability to edit the Mini-Cart style and layout, which is an added feature/advantage over using the Mini-Cart widget.
Caveats
- The Mini-Cart template part being exposed for classic themes that register support will only be available once this pull request in WooCommerce Blocks is merged (which is something we will be doing).
- If you hardcode the Mini-Cart block into a classic theme template using
do_blocks( '<!-- wp:woocommerce/mini-cart /-->' )
, the block styling might need some additional tweaking via CSS. You can also pass in accepted attributes via the block syntax to modify its behaviour and styles. The best way to discover which attributes are available is to use modify the block configuration in a block theme and switch to the code view in the editor to copy and paste the block syntax.
Leave a Reply