Search code examples
angularjsversionsingle-page-applicationbrowser-cache

Angular template versioning


I observed that often unexpected issues occurs with my apps as the user has templates cached in browser. I tried $window.location.reload(true) but even then chrome serves templates from the cache.

Is there an easy solution for this like adding a version query parameter to template URL dynamically using something like Interceptor?


Solution

  • Although on other similar question people sugested to use $templateCache and load everything in one go. This isn't the solution I was looking for as it would increase app first load time by increasing app size and sacrifing on lazy loading provided by angular-ui-router.

    So, below is what I did. Created a value provider for which contains version. This file is minified and include in index page and thus gets loaded along with the page.

    angular.module('my-app').value('version', 'X.X.X');
    

    I noticed that all my templateUrl in states, directives and even in ng-include is loaded via $http service and thus at time of fetching template I can inject a query parameter. So I added following lines in app's config block:

    angular.module('my-app').config(['$httpProvider', function($httpProvider){
        $httpProvider.interceptors.push(['$q', 'version', function($q, version) {
            return {
                'request': function (request) {
                    if (request.url.substr(-5) == '.html') {
                        request.params = {
                            v: version
                        }
                    }
                    return $q.resolve(request);
                }
            }
        }]);
    }]);
    

    So, all my templates are called with version number and now browser waits for new template to load if version is increased. I periodically check for version update via an api. And if a new version is detected, I prompt user to reload the page. On user approval, I reload it via $window.location.reload(true)

    Update

    Following is snippet to check for new version. It can vary according to use case. As we have ad-hoc release cycle here, we check for new version on each window focus and also during first load.

    angular.module('my-app').run(['$rootScope', '$window', 'version', 'configService', function($rootScope, $window, version, configService){
        $rootScope.checkVersion = function () {
            configService.getVersion().then(function (data) {
                if (data.version != version) {
                    // show user a message that new version is available
                    promptUserForReload().then(function () {
                        $window.location.reload(true);
                    })
                }
            });
        }
    
        $window.addEventListener("focus", $rootScope.checkVersion);
    
        $rootScope.checkVersion();
    }])