Dynamic Asset Versioning

We’re proud to announce that we’ve published our first plugin to the WordPress.org repository: Dynamic Asset Versioning.

Dynamic Asset Versioning was designed with one goal: prevent stale CSS and JavaScript from being served in a heavily-cached production environment. It accomplishes this by detecting when a script or style (registered and enqueued using wp_enqueue_script() or wp_enqueue_style(), respectively) is missing an explicit version number and, when such an asset is found, a version number is created dynamically.

What is “cache-busting”?

Cache-busting is the practice of appending a query string to a URI, ensuring that browsers, CDNs, and other caches recognize that a resource has changed.

For assets like stylesheets and JavaScript, we can safely append a query string with some identifier (usually a version number) to ensure that a fresh copy of the asset is downloaded. When we make changes to the asset, we simply increment the version number:

<script src="/path/to/my/script.js?ver=2"></script>

Applying cache-busters in WordPress

When you register a stylesheet or JavaScript file in WordPress (using wp_enqueue_script() or wp_enqueue_style()), you can optionally define the asset version.

When you’re loading third-party scripts (or writing a plugin that you’re distributing), this version number will obviously be the version of the asset or library. Oftentimes, you’ll see something like this in a plugin file:

define( 'MYPLUGIN_VERSION', '1.0.2' );

Then, when registering the script or style, the developer will use the MYPLUGIN_VERSION constant as the asset’s version. When the plugin is updated, the developer only has to change this value once and anyone running the plugin will automatically get served the updated asset.

What happens when our project doesn’t have an explicit versioning scheme, though? We could certainly define a MYTHEME_VERSION constant, but what are the chances that we’ll forget to increment that value?

WordPress attempts to solve this problem for you, by automatically falling back to the current WordPress version. For example, let’s say we’ve registered a script:

wp_register_script(
  'my-handle',
  '/path/to/my/script.js'
);

Since we haven’t specified a version number, WordPress will automatically inject the current WordPress version, giving us a script that looks like this on the front-end:

<script src="/path/to/my/script.js?ver=4.7.0"></script>

That works well for WordPress core scripts, but our script may be updated far more often than WordPress core. How can we make sure our cache-buster is getting updated without having to remember to change MYTHEME_VERSION every time we make a change?

Enter Dynamic Asset Versioning

Dynamic Asset Versioning aims to eliminate that problem by automatically injecting a version number for scripts and styles in your theme without them, derived from the file’s modification time.

You can get started by downloading Dynamic Asset Versioning from the WordPress.org plugin repository, then installing the plugin either as a must-use (MU) plugin (recommended) or a standard plugin

Finally, when you register your script or style, explicitly pass either null or false for the $version argument. You’ll know it’s working when your asset is loaded with a query string like ?ver=1482379108.

Contributing

The source for Dynamic Asset Versioning is available on GitHub and released under the MIT License. Pull requests, bug reports, and other contributions are more than welcome!

A special thanks also goes out to 10up, where I built an earlier iteration of Dynamic Asset Versioning for internal use. While the plugin has been completely rebuilt from the ground-up, 10up still helped to validate the idea and gave me the time to explore the underlying enqueueing mechanisms.

Leave a Reply