Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
Pages: 1
Cache busting CSS and JavaScript
Just wondering what people use for cache busting CSS and JavaScript on their Textpattern-powered sites, if any of you do?
Offline
Re: Cache busting CSS and JavaScript
For files-based resources (when using rvm_css, for example), I tend to append the last-modified timestamp as a query param.
I have a (non-Txp-specific) PHP function I wrote which appends a timestamp to either a single URL, or a bunch of them. If you throw a tag as the 2nd argument, it’ll create full tags from all the URLs given, complete with stamped resources. If I was to Txp-ise it or make it a plugin, the function would become a lot simpler as I could use tag()
and join_atts()
.
Doesn’t work for database CSS though as it’s not (currently) timestamped.
For the vaguely interested, here’s the code. Not fully tested yet, just an idea I had and jotted down in a ‘Maybe to do one day’ scratchpad:
/**
* Add a timestamp to the given resource for cache-busting purposes.
*
* If passed a single $url, just that entry is stamped.
* If passed an array and an HTML tag (script or link) it generates the
* relevant tag, with the given attributes.
*
* @param string|array $url URL(s) to append timestamps to
* @param string $tag HTML tag to create from each $url
* @param array $atts HTML attributes to apply to each $tag
* @return string
*/
function stampFile($url, $tag = null, $atts = array())
{
if (!is_array($url)) {
$url = array($url);
}
$out = array();
foreach ($url as $thing) {
// Permitted tags:
// -> key: 'url' attribute name for this tag.
// -> sc: whether the tag is self-closing or not.
$ctags = array(
'script' => array('key' => 'src', 'sc' => false),
'link' => array('key' => 'href', 'sc' => true),
);
$parts = parse_url($thing);
$path = ((strpos($parts['path'], '/') === 0) ? $_SERVER['DOCUMENT_ROOT'] : '') . $parts['path'];
$ver = filemtime($path);
$thing .= ((isset($parts['query'])) ? '&' : '?') . 'mstamp='.$ver;
if ($tag === null) {
$out[] = $thing;
} else if (array_key_exists($tag, $ctags)) {
$attlist = array();
$attmerge = array($ctags[$tag]['key'] => $thing) + $atts;
foreach ($attmerge as $key => $val) {
$attlist[] = htmlspecialchars($key) . '=' . '"' . htmlspecialchars($val) . '"';
}
$tagout = '<' . $tag . ($attlist ? ' ' . implode(' ', $attlist) : '') . '>';
if ($ctags[$tag]['sc'] === false) {
$tagout .= '</' . $tag . '>';
}
$out[] = $tagout;
}
}
return implode("\n", $out) . (($tag === null) ? '' : "\n");
}
It currently only permits ‘script’ and ‘link’ tags to be created, but it could be exetended to cater for images or whatever.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Cache busting CSS and JavaScript
Bloke wrote #281230:
For files-based resources (when using rvm_css, for example), I tend to append the last-modified timestamp as a query param.
+1. I don’t use it regularly, but I tack on GMT epoch time as a query:
<link href="//example.com/default.css?1401885603" media="screen" rel="stylesheet" type="text/css">
Offline
Re: Cache busting CSS and JavaScript
Thanks, and yes I am referring to flat files of CSS and JavaScript.
@pete
I want to avoid using query strings in the URL, as this article explains.
Offline
Re: Cache busting CSS and JavaScript
I think I can work something out using a combination of Grunt and rah_flat to write UNIX epoch time onto the CSS/JS URLs in Textpattern page/form templates when copied from my src
directory to the public
directory.
Jukka did a similar thing when he set up the build process for this Textpattern forum, so I’ll reverse engineer that.
Thanks anyway!
Offline
Re: Cache busting CSS and JavaScript
philwareham wrote #281232:
I want to avoid using query strings in the URL
Sure, if you want to use revisioned or datestamped filenames instead of query params you can use the htaccess route and serve resources that way. Equally valid. A good example that I’ve used, if you don’t mind having to remember to reapply the .htaccess
patch each upgrade.
The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.
Txp Builders – finely-crafted code, design and Txp
Offline
Re: Cache busting CSS and JavaScript
philwareham wrote #281232:
I want to avoid using query strings in the URL, as this article explains.
Makes sense. Consider me schooled -thanks for the link.
Last edited by gaekwad (2014-06-04 13:33:12)
Offline
Re: Cache busting CSS and JavaScript
Jukka’s solution (for forum templates, but it equates to the same principle as Textpattern templates) was to put a placeholder hook into the filenames of CSS/JS links source template files in src
build files and use Grunt to automatically write a UNIX Epoch timestamp into that hook as the build copied those files to public
.
<link rel="stylesheet" href="style/Textpattern/css/main.@@timestamp.css">
I think I’ll use that as a basis, seems like the least manual effort.
Offline
Re: Cache busting CSS and JavaScript
In Txpmag we simply read the modification timestamp:
<txp:variable name="assets_url" /><txp:php>
$file = trim(parse('<txp:yield />'));
$path = pathinfo($file);
$time = filemtime(txpath . '/../assets/' . $file);
echo $path['dirname'] . '/' . $path['filename'] . '.' . $time . '.' . $path['extension'];
</txp:php>
Save as a asset
from and use like so:
<txp:output_form form="asset">css/main.css</txp:output_form>
And it then returns http://assets.example.tld/css/main.123456789.css
This can be then combined with a caching solution, like Memcached too:
<txp:rah_memcached>
<txp:output_form form="asset">css/main.css</txp:output_form>
</txp:rah_memcached>
Offline
Re: Cache busting CSS and JavaScript
@Gocom
Nice solution, thanks!
Offline
Pages: 1