Versioning of static resources in WordPress

If you deal with WordPress you soon notice that static resources like style sheets or scripts get included with the parameter “ver”, as for example in the “Hemingway” theme:

href='http://server.example/wp-content/themes/hemingway/style.css?ver=4.1'

If you then validate the website, as for example with Pingdom, the “ver” parameter will be treated as a problem for efficient caching since content delivered by URLs with parameters may not be stored in a cache but fetched from the original server for every single request.

On the other hand the version information is important for the correct function of themes and plugins, especially when they get updated – if you are an author in this area you should definitely pay attention to the note at the end of this post.

Removing the parameters from the URL – a good idea?

Some people suggest to add a WordPress filter for the actions script_loader_src and style_loader_src to remove the “ver” parameter. There are also plugins which do this.

But this is not a good idea!

Explanation:

Stylesheets and scripts will be stored in the local cache by the browser. There they will remain a couple or days or even longer depending on the configuration of the server and the expiration time. Setting a long expiration time for static resources is a good thing to avoid unneccesary requests for things which don’t change often anyway.

If you now update WordPress, a theme or a plugin, the “ver” parameter will usually change and the browser will request the new version from the server since the cache content is no longer valid due to the changed parameter in the URL.

But if the parameter “ver” is missing, the URL remains unchanged and the browser will not request the resource from the server as it already has a cached copy. Visitors may get a mixture of old and new resources which leads to a wrong or completely unuseable display.

So the “ver” parameter is not needless but ensures that a browser will not try to use old versions from the local cache but request the new version if required.

A more elegant approach: parameters as part of the URL

John Beales proposed a more elegant approach which modifies the URLs for scripts and style sheets in WordPress in a way that the URL will be unique for every version but without the “ver” parameters at the end. This also requires a rewrite rule in the webserver, since the URLs do no longer address an existing file on the server.

Step 1: Modifying the URLs in WordPress

To modify the generated URLs in WordPress you have to extend the functions.php of your theme with the following code:

function my_versioned_url($url, $defaultversion = false) {
    // don't bother for the admin
    if(!is_admin()) {
        // parse the URL
        $parts = parse_url($url);

        // and the querystring
        $query = wp_parse_args($parts['query'], array());

        // check if there's a version in the querystring. If so, do more.
        if(isset($query['ver']) || false !== $defaultversion) {
            if(isset($query['ver'])) {
                // prepend "/res-" + {version value} to the *path*
                $parts['path'] = '/res-'.$query['ver'].$parts['path'];

                // unset the version in the querystring,
                // since it's in the path now.
                unset($query['ver']);
            } else {
                $parts['path'] = '/res-'.$defaultversion.$parts['path'];
            }

            // if this is a PHP file just let it be.
            if(!preg_match( '~\.php$~', $parts['path'])) {
                // start rebuilding the URL string
                $url = $parts['scheme'].'://'.$parts['host'].$parts['path'];

                // see if there's still anything in the query
                if(count( $query ) > 0) {
                    // rebuild query with whatever remains
                    $parts['query'] = build_query( $query );

                    // append it to the URL string
                    $url .= '?'.$parts['query'];
                }
            }
        }
    }

    return $url;
}

// hook onto the filters
add_filter( 'style_loader_src', 'my_versioned_url' );
add_filter( 'script_loader_src', 'my_versioned_url' );

Explanation:

The function my_versioned_url() will be used as filter for loading style sheets and scripts in the frontend and gets two parameter: the URL of the file to be loaded and an optional version number which WordPress will add as “ver” parameter to the URL. As result the function will return a modified URL which is build according to the following scheme:

http://<servername>/res-<version>/<url>

Based on the example from the beginning this would then look like this:

http://server.example/res-4.1/wp-content/themes/hemingway/style.css

Step 2: Add a rewrite rule in Apache

For the correct handling of the modified URLs you just need two lines which you may add in the file .htaccess at the root of the website:

RewriteEngine on
RewriteRule ^res-([\d\.\-a-zA-Z]+)/(.*) $2?ver=$1 [L]

Important: If you want another prefix instead of “res-” you have to modify this in the filter function as well as in the rewrite rule!

A note to authors of themes and plugins

Unfortunately it is not mandatory to provide a version number when enqueuing  scripts or style sheets in themes or plugins. If no specific version is given, WordPress will automatically use its own version (for example 4.2.1) as “ver” parameter – but this also means, that the version will remain unchanged when the theme or plugin gets updated but the same WordPress version will still be used. Eventually this will cause browsers to use an old cached version of scripts and style sheets and people will complain that the plugin or theme stopped working properly after its update!

To avoid problems you should always add a version parameter for all scripts and style sheets as shown in the following example:

wp_register_style(
    'my-cool-widget',
    plugins_url('styles/widget.css', __FILE__),
    array(),
    '1.0.0' // <-- This is the version of YOUR widget, not WordPress!
);
wp_enqueue_style('my-cool-widget');

And of course you should also take care that an updated version also gets a new version number, when the enqueued scripts or style sheets changed!

2 thoughts on “Versioning of static resources in WordPress”

  1. Robert

    It can also choose which query string you keep or remove:

    https://wordpress.org/plugins/remove-query-strings-littlebizzy/

    1. Arno Welzel

      Thanks for the suggestion. But removing version information from the URL is not really recommended because it may cause problems when theme or addons get updated – as I explained my article:

      So the “ver” parameter is not needless but ensures that a browser will not try to use old versions from the local cache but request the new version if required.

Leave a Comment to Robert Cancel Comment

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