Complex manual cache-busting with RequireJS

July 24, 2015 | No comments

RequireJS gives you the urlArgs property in require.config to add cache-busting. You can use a version, so the browser grabs updated files only when you change the version number:

require.config({
    urlArgs: 'v=1.00'
});

You can generate a time-based number so that the browser will grab updated files every single time:

require.config({
    urlArgs: 'v=' + (new Date()).getTime()
});

You can use a combo of the two methods, to prevent caching on a certain environment but enable it on another:

require.config({
    urlArgs: document.domain==='localhost' ? 'v=' + (new Date()).getTime() : 'v=1.00'
});

If you want the urlArgs to be applied to the main JS file as well, you’ll need to define them in your index.html file like so:

<script type="text/javascript">
var require = {
    urlArgs: document.domain==='localhost' ? 'v=' + (new Date()).getTime() : 'v=1.00',
    deps: ['js/common/app']
};
</script>
<script src="js/common/libs/require.js"></script>

If you want your urlArgs to have logic that takes the URL into account, you’ll have to make a modification to the require.js file to allow urlArgs to be a function that receives arguments. Replace the following:

return config.urlArgs ? url + ((url.indexOf('?') === -1 ? '?' : '&') + config.urlArgs) : url;

With this:

if(config.urlArgs){
    if(typeof config.urlArgs === "function"){
        return url + ((url.indexOf('?') === -1 ? '?' : '&') + config.urlArgs.call(this, arguments));
    }else{
        return url + ((url.indexOf('?') === -1 ? '?' : '&') + config.urlArgs);
    }
}else{
    return url;
}

Then in index.html file add your url-based logic. The example below would be ideal for a group of apps that all share a handful of common JS modules.

<script type="text/javascript">
var require = {
    urlArgs: function(urlObj){
        if(urlObj[0][urlObj[0].length-1]==='app'){
            //Always cachebust the main app file
            return 'bust=' + new Date().getTime();
        }else if(document.domain==='localhost'){
            //Always cachebust on local
            return 'bust=' + new Date().getTime();
        }else if(urlObj[0][0].indexOf('/common')>-1){
            //Use the version # in require.config for all common modules
            return this.config.appUrlArgs;
        }else{
            //Set version # for sub-app modules 
            return 'v=1.00';
        }
    },
    deps: ['js/common/app']
};
</script>
<script src="js/common/libs/require.js"></script>

The version number for all common files is saved in the main app file (which is why we don’t want the browser to ever cache it):

require.config({
    commonUrlArgs: 'v=1.05'
});

 

Leave a Reply