Search code examples
htmlangularjsbrowser-cacheoclazyload

How to reload templates (html) when releasing a new version of a SPA?


I'm currently running into trouble when releasing new versions of my SPA since the html templates are being cached by the browser.

My SPA uses Angular 1.5, ocLazyload and ui-router. I have configured gulp tasks to use cache-busting technique (with gulp-rev), and it is working pretty well, at least with the script and css files. However, when we have changes on html files the browser keeps loading the old version. Sometimes even refreshing the page with Ctrl+F5 doesn't solve the problem and it keeps showing the old version of html.

In addition, configuring the browser to not make cache of html files isn't desirable (specially for mobile), since html changes may occur not very often.

Is there any good solution that address this problem for fetching html files only when there is new versions of it?

Thanks in advance!


Solution

  • As you are using gulp, you could make use of gulp-angular-templateCache, which is a gulp plugin to collect all your html files, concatenate them into a single javascript file and add them to AngularJS' $templateCache based on the file path.

    gulp.task('default', function () {
        return gulp.src('app/**/*.html')
            .pipe(templateCache({
                module: 'yourModuleName'
            }))
            .pipe(gulp.dest('dist'));
    });
    

    The resulting JavaScript file contains something like:

    angular.module('yourModuleName').run([$templateCache,
        function($templateCache) {
            $templateCache.put('app/path/to/some-template.html",
                // some-template.html content comes here (escaped)
            );
        }
    ]);
    

    You could now add this file to your bundle, any changes to your html file will update the content of your bundle hence result in an updated cache buster.

    But if you do not want the entire bundle to be updated, you could keep them seperated and ensure the file get's loaded after your bundle.

    Note: both of the above approaches do break the cache for all html files once one of them has changed, but all of those html files are retrieved using a single call.

    An alternative approach could be to add cache busters to your html files and update all the usages of that file to include the cache buster's hash. But I'm not really a fan of this approach.

    Edit: The first approach is the one I use in my gulp-based projects. However, these days I'm using AngularJS with Webpack (See my starter) and I'm using an approach comparable to Midhun Darvin's 3th method (see here), but instead of requirejs I'm making use of webpack. However, keep in mind that this approach (using either requirejs or webpack) will result in the html files being added to the javascript file containing your angularjs code. This means any change to a javascript file will brake the cache for all your html files as the cache buster will be updated.