As the owner of a WordPress website or blog you may know the situation: you artificially made some design changes in the admin area and as soon as you preview the page the changes are simply not there – no matter how hard you try. That’s when a technique called Cache Busting is required.
Cache is in the Way
One of the many reasons for this behaviour may be the browser’s caching mechanisms. Basically it makes a lot of sense for the browser to not reload all the Stylesheets and JavaScript files each and every time that a user visits your page because the frequency with that these files change in general is very low. That’s why a lot of websites instruct the browser to cache static files like CSS and JavaScript for e.g. 1 year. Therewith lots of bandwidth and downloading power on the browser side and requests on the server side is saved and the website can be rendered dramatically faster.
A good in-depth explanation of various browser caching mechanisms can also be found here.
The downside of this behaviour is, that the browser needs to know when the contents of the (CSS or JavaScript) file has changed, because otherwise he simply will not re-download it and use the version from its internal cache instead. That’s the case when the user does not see your design changes as long as he does not force his browser to clear the cache (which no one does).
The solution
One simple way to solve this problem is to change the filename or path of the CSS or JavaScript every time the file contents changes. (Note: By the way, there are also some other ways using E-Tags or Last-Modified header, but this one is the simplest to use). This process of invalidating the cache is known as “Cache Busting”.
By default WordPress adds the installed WordPress version to each CSS or JavaScript file like this:
http://demo.wordpress.recolize.com/wp-includes/js/comment-reply.min.js?ver=5.2.3
(This is by the way not so clever as it easily reveals the WordPress version.)
The WordPress version is attached so that after each upgrade – which probably has some theme upgrades as well – the browser will request the new files.
Most of the WordPress themes also use static style sheet files, that are generated each time you change some styles in the backend. The problem is that the user’s browser does not notice this change as long as the WordPress version does not change.
The solution to this problem is very simple: we just modify the “ver” parameter to include a so-called hash of the change date of the file. Therewith each time the file is regenerated, the last modified date is changed and therewith the hash changes. This means the browser notices a new filename and requests our modified file from the server. Our filename now looks like this: http://demo.wordpress.recolize.com/wp-includes/js/comment-reply.min.js?ver=1534832128
Below you can find the code snippet that must be placed e.g. in the WordPress functions.php file:
<?php /** * WordPress Cache Busting made simple. * * @author Recolize GmbH <service@recolize.com> * @license http://opensource.org/licenses/GPL-3.0 GNU General Public License Version 3 (GPLv3) * * This script is based on * @see https://medium.com/@futuremediagr/easy-versioning-for-css-and-js-files-in-wordpress-e7dad756586c * @see https://gist.github.com/ocean90/1966227 */ function set_custom_ver_css_js($src) { // Don't touch admin scripts. if (is_admin()) { return $src; } $_src = $src; if (strpos($_src, '//') === 0) { $_src = 'http:' . $_src; } $_src = parse_url($_src); // Give up if malformed URL. if (false === $_src) { return $src; } // Check if it's a local URL. $wordPressUrl = parse_url(home_url()); if (isset($_src['host']) && $_src['host'] !== $wordPressUrl['host']) { return $src; } $filePath = ABSPATH . $_src['path']; if (file_exists($filePath) && strpos($src, 'ver=') !== false) { $src = add_query_arg('ver', filemtime($filePath), $src); } return $src; } function css_js_versioning() { add_filter('style_loader_src', 'set_custom_ver_css_js', 9999); add_filter('script_loader_src', 'set_custom_ver_css_js', 9999); } add_action('init', 'css_js_versioning');