如何在发布新版本的 SPA 时重新加载模板 (html)?

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

我目前 运行 在发布我的 SPA 新版本时遇到了麻烦,因为 html 模板正在被浏览器缓存。

我的 SPA 使用 Angular 1.5、ocLazyload 和 ui-router。我已将 gulp 任务配置为使用缓存清除技术(使用 gulp-rev),并且它运行良好,至少对于脚本和 css 文件。但是,当我们对 html 文件进行更改时,浏览器会继续加载旧版本。有时即使使用 Ctrl+F5 刷新页面也无法解决问题,它一直显示旧版本 html.

此外,将浏览器配置为不缓存 html 文件是不可取的(特别是对于移动设备),因为 html 更改可能不会经常发生。

有什么好的解决方案可以解决这个只有在有新版本时才获取 html 文件的问题吗?

提前致谢!

由于您正在使用 gulp,您可以根据文件路径使用 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

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

生成的 JavaScript 文件包含如下内容:

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

您现在可以将此文件添加到您的包中,对您的 html 文件的任何更改都会更新您的包的内容,从而导致更新缓存破坏器。

但是如果您不想更新整个包,您可以将它们分开并确保文件在您的包之后加载。

注意:一旦其中一个文件发生更改,上述两种方法都会破坏所有 html 文件的缓存,但是所有这些 html 文件都是使用一次调用检索的。

另一种方法是将缓存清除器添加到您的 html 文件并更新该文件的所有用法以包含缓存清除器的哈希。但我不太喜欢这种方法。

编辑:第一种方法是我在基于 gulp 的项目中使用的方法。然而,这些天我在 Webpack 中使用 AngularJS(参见我的 starter) and I'm using an approach comparable to Midhun Darvin's 3th method (see here),但我使用 webpack 而不是 requirejs。但是,请记住,这种方法(使用 requirejswebpack)将导致 html 文件被添加到包含 angularjs 的 javascript 文件中代码。这意味着对 javascript 文件的任何更改都将阻止所有 html 文件的缓存,因为缓存破坏器将被更新。

我在一个项目中遇到了这个问题。我尝试了这些方法。

方法一:设置不同状态的缓存属性false

var core = angular.module('app.core');
core.cofigure(configure);

configure.$inject = ['$stateProvider'];

// Configuration Function
function configure($stateProvider){

    $stateProvider
          .state('login', {
            url: '/login/:redirect/:viewId',
            cache: false, // Here i have set the cache property to false
            templateUrl: 'app/layout/login.html' 
          })
          .state('home', {
            url: "/home",
            cache: false, // Here also
            abstract: true,
            templateUrl: 'app/layout/container.html'
          });
}

现在这个方法很好,但它在随机时间和 Internet Explorer 中不起作用。

方法 2:向模板添加时间戳 URL。

 // I created a timestamp string with the current time.
 var date = new Date().getTime().toString();

 $stateProvider
          .state('login', {
            url: '/login/:redirect/:viewId',
            cache: false, 
            // Now i append it here
            templateUrl: 'app/layout/login.html' +'?' + date 
          })
          .state('home', {
            url: "/home",
            cache: false, 
            abstract: true,
            templateUrl: 'app/layout/container.html' + '?' + date // Here also.
          });

此方法是我们在搜索此问题的可能修复方法后决定的。但是,在这种情况下不会发生缓存。每个对模板文件的 GET 请求都是不同的,它会保证加载的模板是更新的模板。但是,如果您构建的 Web 应用程序具有大量模板并且客户端性能至关重要,则此方法将无济于事。

方法 3:需要模板

我推荐这个方法。您可以在应用程序中使用 require.js 在 javascript 执行时加载模板。这将在 运行 应用程序出于开发目的以及当您缩小生产代码时加载模板。由于模板已加载到 javascript 代码中,因此在部署到生产环境时也不必保留 html 模板文件。

$stateProvider
          .state('login', {
            url: '/login/:redirect/:viewId',
            // Note 'template' and not 'templateUrl'
            template: require('app/layout/login.html')
          })
          .state('home', {
            url: "/home",
            abstract: true,
            template: require('app/layout/container.html')
          });

我推荐一种类似于@Midhun Darvin 的选项 2 的方法(因此我使用他们的代码作为基础)。不使用日期,而是使用版本号。对于每个版本,您只需要记住更新版本号,所有 html 文件的缓存都会被破坏。

 // update this with every release
 var version = 0.1.0;
 // make make this easier so you don't have to add query strings to all your template calls
 var v = "?v=" + version;

 $stateProvider
     .state('login', {
         url: '/login/:redirect/:viewId',
         cache: false, 
         templateUrl: 'app/layout/login.html' + v // version added to bust cache
     })
     .state('home', {
         url: "/home",
         cache: false, 
         abstract: true,
         templateUrl: 'app/layout/container.html' + v // version added to bust cache
     });