ProcessWire 3.0.98 master

This week we've got a new version on the master branch, which is version 3.0.98. This version contains relatively minor fixes relative to the existing master version 3.0.96, but it is still 18 commits worth, and likewise worth the upgrade. For more details, see the master branch commit log for dates after March 16, 2018. Minor version upgrades will likely continue on the master branch until we get back into larger updates, PRs and additions on the dev branch. If you are running 3.0.96 I do think it's worth upgrading to 3.0.98, though there's also no urgency to it.

ProCache “buster” — browser cache busting for files

All of the file assets that your website outputs are generally cached by your web browser. Common examples are images (jpg, png, gif, etc.), documents (pdf, doc, etc.), stylesheets and javascript files, but of course it could be any type of file. And it's a desirable thing that the browser caches these, because otherwise it would have to reload them on every single request, slowing down the browsing experience, and taxing the server.

But this browser caching also creates a problem. If you change the contents of any file, a return visitor will likely see the older version of the file, rather than the newer one you replaced it with. This happens when the contents of a file changes, without the filename changing. For instance, lets say you had a photo in on your website, but later realized there was a problem in the lower half of the photo, so you went back and cropped the photo to be the top half instead. The photo changed, but the filename didn't. Users that saw the original version before will continue to see it, rather than your new cropped version (unless they've cleared their browser cache).

The same situation arises anytime you replace a file without also changing the name of it, whether it's a file you've uploaded in ProcessWire, or a file you've uploaded through FTP, or by some other means. Most experienced web developers are likely very familiar with this topic, though since many of us spend our day with the browser developer tools open (which usually implies having the browser cache disabled), we might miss it during development. Or at least I often do. So when browser cache-busting features were requested for ProCache in the ProCache forum, that really resonated with me, and I got to work shortly afterwards, and Buster is the result.

The latest beta of ProCache comes with both a browser cache-busting API, and automatic updating of linked assets for cache-busting in HTML output and CSS files and dynamic output. Because "browser cache busting" is kind of a mouthful, we're calling this new feature just "buster". Below is a screenshot of the Buster tab in the ProCache configuration utility:

How ProCache Buster works

Buster updates the URL of files to contain a string that uniquely represents the version of the file. The URL of the file stays the same so long as the contents of the file does. But as soon as the contents of the file changes, so does the URL. Buster does this by examining the modification time of files, and using that modification time as part of the URL. This is the most common cache-busting technique, as it is very reliable. But Buster takes it a little further and uses a minified version of the time which is relative to the date the site was installed, and then converts it to a base-36 string. This ensures that file modification times can be represented with very short strings rather than full unix timestamps.

Buster can represent the file's unique cache-busting string as part of a query string in the URL, or as part of the filename. See the “Buster URL type” field in the screenshot above. What type you use doesn't matter much in terms of results that it produces. Years ago, some proxy servers could be configured not to cache file assets with query strings. That made it preferable to have the version as part of the filename rather than the query string. But as far as I can tell, this is no longer the case and you are unlikely to ever run into such a situation any more. Nevertheless, I put the option to have the version as part of the filename, just in case anyone prefers it for one reason or another. Here are examples of actual Buster URLs with the first using the query string format, and the second using the filename format ("36pxs" is the base-36 cache-busting string in this case):

  • /site/assets/files/1035/test.jpg?36pxs
  • /site/assets/files/1035/test.36pxs.jpg

Buster is available to use from the API and has its own API variable, $buster. Buster can also perform its job in the background, automatically. Using the API may be preferable for developers who want the most control and to exercise their own judgment as to which files are important to cache-bust and which are not. For instance, maybe there are situations where a change to a file really doesn't matter... such as a photo where the only change was to increase the compression to reduce the file size. On the other hand, automatic cache busting is preferable for those that want a turn-key solution that they can just enable and be done with it. We'll discuss both options in the following sections.

ProCache Buster API

Using Buster in API mode means using the $buster->url() method, like this:

<img src="<?= $buster->url('/url/to/file.jpg') ?>" alt="file" />

Another example:

<a href="<?= $buster->url('/files/file.pdf') ?>">View PDF</a>

You can use that url() method on any file. Simply give it the URL to the file, and it'll return a cache-busting URL consistent with the format that you selected in the ProCache configuration. There's also the $buster->httpUrl() method, which does the same thing, but returns a cache-busting URL with the current scheme and hostname included:

$url = $buster->httpUrl('/files/report.csv');

ProcessWire's file and image fields (represented by Pagefile and Pageimage objects) already have an uppercase URL property which always returns a cache-busting version of the file's URL. This is the case whether you've got ProCache installed or not. But in ProcessWire master 3.0.96 or newer, ProCache Buster updates that URL property to use ProCache's enhanced buster, rather than the one built-in to the core. Meaning, even the core file field API benefits from Buster:

foreach($page->images as $image) {
  echo "<img src='$image->URL'>";
}

Automatic browser cache busting

If you want Buster to automatically bust assets in your HTML (and optionally CSS) output, ProCache Buster has you covered. By default, it will bust all matching files referenced in in your HTML/CSS output. Or if you prefer it, it can be configured to only bust file URLs that you've appended with ?buster (which of course will be removed in the resulting URL).

When it comes to HTML output, Buster will automatically detect files referenced in HTML tag attributes (such as src, srcset and href), and if the file extension matches one it's allowed to bust, it will bust the URL to that file automatically. Buster will also bust URLs specified in in style="..." attributes of HTML tags, and it will also look for inline <style>...</style> sections of the document and update URLs that appear in that inline CSS as well.

When it comes to CSS files, if enabled, Buster automatically updates URLs referenced by CSS files created by ProCache's CSS merge/minify. For example, it will update those background-image: url(...); references so that they are cache-busting.

Cache busting considerations and caveats

The filenames created for CSS and JS files merged/minified by ProCache already use cache-busting filenames (and always have), so you do not need to use Buster for those. Instead, Buster is useful for the files you might reference from within those CSS files.

Cache-busting of file-based assets takes some logic and thus requires PHP to run. Since ProCache’s main job is to provide a static cache (preventing PHP from running), that's something to keep in mind. As you might have guessed, the cache and the cache-buster have a little bit different goals. Simply replacing a file on your server with a new version won't trigger cache busting immediately when the pages using such files are delivered from a static cache. As a result, Buster is more effective on output that has a relatively low static-cache expiration time (or is not cached), so that Buster can run at regular intervals. However, given that browser cache time (which might be a month, year or more) is almost always greater than server static cache expiration time (which is most often an hour, a few hours, or a day), Buster is likely to be very helpful even in cases where the static cache might prevent it from being immediate.

Busting of assets linked in CSS files (like images) also takes some consideration. New merged/minified CSS files generally aren't created unless something about one of the files in the merge changed. As a result, simply replacing an image linked from a CSS file isn't enough, since the cache-busting strings are generated when the CSS is created. You can force re-creation of the CSS files by either changing something (anything) in any of the CSS files contributing to the merge, or you can check the box to clear the CSS file cache in ProCache. For these reasons, cache busting in CSS is certainly worthwhile, but not nearly as much so as cache-busting in HTML output.


This week was Spring Break, so the kids were home from school and I didn't get enough time in the office to finish up testing the new ProCache version this week in order to release it. But I expect that this new version of ProCache, which includes Buster, among other updates, will be available for download from the ProCache support board this weekend or next week. Thanks for reading! Hope to see you at ProcessWire Weekly and have a great weekend!


Comments

  • Jonas K

    Jonas K 2 months ago 00

    Awesome addition to an already great plug-in!
    Can you tell us when the automatic cache busting will be ready for deployment?
    It's a feature that would be perfect for a client project that I am working on. I have buster in use already but an automated option would save a ton of work.

Post a Comment

Your e-mail is kept confidential and not included with your comment. Website is optional.