Custom version-based cache busting for WordPress CSS/JS assets

WordPress appends a query var like ?ver=4.2.1 to CSS/JS URIs when building <link> and <script> tags. When WP’s version changes (eg, from 4.2.1 to 4.2.2), the query var changes too, causing browsers to bypass their cached assets and forcing a fresh version to be requested from the server. This works well for core assets, because they generally don’t change between WP releases. But for assets loaded by plugins and themes – which don’t always provide their own ver string when enqueuing their scripts and styles – it’s not a perfect system, since browser caches will only be busted when WordPress core is updated.

I built a small filter for the CUNY Academic Commons that works around the problem by appending our custom CAC_VERSION string to all ver query vars. This ensures that users will get fresh assets after each CAC release, whether or not that release includes a WP update.

Note that this code is pretty aggressive: it busts all CSS/JS caches on every release. You could use the $handle argument to do something more fine-grained. Note also that this technique doesn’t work equally well for all caching setups; see this post for an alternative strategy, based only on filename. Proceed at your own risk.

1 thought on “Custom version-based cache busting for WordPress CSS/JS assets

  1. Eric Lewis

    While building a new stack recently, I fished around for a solution to this problem too.

    Rails’ asset pipeline is responsible for making static assets available with application versioning in mind. They fingerprint the filename (similar in convention to Dominik’s tutorial), and their documentation cites a few reasons why caching via query arguments is problematic.

    I implemented a small build which uses a gulp plugin to fingerprint assets in a deterministic manner based on file contents and do lookups in a JSON manifest to enqueue the proper file.

    Reply

Leave a Reply to Eric Lewis Cancel reply

Your email address will not be published. Required fields are marked *