Skip to content

Instantly share code, notes, and snippets.

@ecowden
Created January 25, 2013 21:01
Show Gist options
  • Save ecowden/4637806 to your computer and use it in GitHub Desktop.
Save ecowden/4637806 to your computer and use it in GitHub Desktop.
Cache busting for AngularJS partials is easy
/*
* Decide on your cache-busting strategy. In this example, we use the current timestamp, which will
* force a change every time the app is visited, but not every time the partial is loaded within a
* visit. Even better would be to use a hash of the file's contents to ensure that the file is always
* reloaded when the file changes and never reloaded when it isn't.
*/
var cacheBustSuffix = Date.now();
// Optionally, expose the cache busting value as a constant so other parts of your app can use it.
ngModule.constant("cacheBustSuffix", cacheBustSuffix);
// Configure routing
ngModule.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
//Append our cache busting value as a query parameter when we specify our templates
templateUrl: 'partials/dashboard.html?cache-bust=' + cacheBustSuffix,
controller: "DashboardCtrl"
});
...
$routeProvider.otherwise({redirectTo: '/'});
}]);
/*
* What if we include a partial within another and it's not referenced directly as a route?
* This is one possible approach, though you may want to organize things differently.
*/
ngModule.controller("EnterTimesheetCtrl", [
"$scope", "cacheBustSuffix", // we're using the constant declared above
function EnterTimesheetCtrl($scope, cacheBustSuffix) {
$scope.editableTemplateUrl = "partials/timesheet/editableTimesheet.html?cache-bust=" + cacheBustSuffix;
}
<div ng-include src="editableTemplateUrl"></div>
@airtonix
Copy link

airtonix commented Feb 9, 2014

so this gist only works when you use the (not recommended) method of timestamp query parameters.

Where's your example for when each template has it's file name changed to include it's own md5 hash?

@whatisboom
Copy link

I'm assuming @airtonix has this figured out, but for anyone else who ends up here.

Change line 33 to something like:

$scope.editableTemplateUrl = "partials/timesheet/editableTimesheet."+ cacheBustSuffix +".html";

and your server config will need to support the wildcards in the filename

My nginx config has something like:

    # Cache Busting
    location ~* ^/assets/(.*)\.[0-9]+\.(css|js)$ {
        try_files $uri /assets/$1.$2 =404;
        add_header Vary Accept-Encoding;
        expires max;
    }

Copy link

ghost commented Sep 24, 2015

A far superior method to all this complexity, I've found, is a simple directive applied to the element with the ng-include.

ng.directive('ng-include-no-cache', [
        '$templateCache',
        function($templateCache) {
            var directive = {
                restrict: 'A',
                scope: false,
                link: function(scope, element, attributes) {
                    scope.$parent.$watch(attributes.ngInclude, function(newValue, oldValue){
                        $templateCache.remove(oldValue);
                    });
                }
            };
            return directive;
        }
    ]);

@wallter
Copy link

wallter commented Dec 2, 2016

Finally got sick and tired of this problem and came up with a different solution — that seems simpler and doesn't require any extensive configuration.

var __version_number = 6.0; // cacheBustSuffix = Date.now('U'); // 'U' -> linux/unix epoch date int

app.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push(function () {
    return {
      'request': function (config) {
        // !!config.cached represents if the request is resolved using 
        //      the angular-templatecache
        if (!config.cached) {
          config.url += ( (config.url.indexOf('?') > -1) ? '&' : '?' ) 
            + config.paramSerializer({v: __version_number});
        } else if (config.url.indexOf('no-cache') > -1) {
          // if the cached URL contains 'no-cache' then remove it from the cache
          config.cache.remove(config.url);
          config.cached = false; // unknown consequences
          // Warning: if you remove the value form the cache, and the asset is not
          //          accessable at the given URL, you will get a 404 error.
        }
        return config;
      }
    }
  });
}]);

This will result in all of your app's URL's getting the suffix of '[?|&]v={{date}}' and if the URL being resolved is in the $templateCache && the URL contains 'no-cache' it will be forced to resolve every time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment