One of the biggest pains in web development has to be caching! Can't live with it but most definitely can't live with out. I was recently involved in a discussion around ways to cache bust in Modx and came up with a really simple little snippet that adds the file modified timestamp to a query parameter for the file. Check it out
<?php
$file = $modx->getOption('file', $scriptProperties);
$output = $file;
$filePath = str_replace('//','/',MODX_BASE_PATH . $file);
if(!is_null($filePath) && file_exists($filePath)) {
$output .= '?v=' . filemtime($filePath);
}
return $output;
// Usage:
// <link rel="stylesheet" href="[[!cacheBust? &file=`/assets/css/style.css`]]">
// <script src="[[!cacheBust? &file=`/assets/js/script.js`]]"></script>
Call the snippet uncached (so it runs every time the page loads), then when you make a change to the file it'll update the cache bust parameter:
Output:
<link rel="stylesheet" href="/assets/css/style.css?v=1688118541">
<script src="/assets/js/script.js?v=1688118541"></script>
There is quite a lot of discussion around best practices with cache busting assets, should you use a query parameter i.e. style.css?v=12345
or rename the file style.12345.css
. If you swing more to file renaming you could update the snippet to:
<?php
$file = $modx->getOption('file', $scriptProperties);
$output = $file;
$filePath = str_replace('//','/',MODX_BASE_PATH . $file);
$fileArr = explode('.', $file);
$ext = array_pop($fileArr);
if(!is_null($filePath) && file_exists($filePath)) {
// Add the file modified timestamp to the filename
array_push($fileArr, filemtime($filePath));
}
// Add the extension back
array_push($fileArr, $ext);
// turn the array back to a string
return implode('.', $fileArr);
// This will return something like
// <link rel="stylesheet" href="/assets/css/style.1688118541.css">
Then you can use htaccess to rewrite the file name like so
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+).(\d+).(js|css)$ $1.$3 [L]
However, a word of caution! In Strategies for Cache-Busting CSS by Chris Coyier he advises against this method due to the additional load filemtime()
puts on the server.
The alternative method is to create a system/ context setting (or use an Extra like Client Config) specifically for cache busting then you can use it in your templates like:
<link rel="stylesheet" href="/assets/css/style.css?v=[[!++css_bust:tag]]">