2

由于浏览器正在缓存 html 模板,因此我在发布新版本的 SPA 时遇到了麻烦。

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

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

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

提前致谢!

4

3 回答 3

4

我在我从事的一个项目中遇到了这个问题。我试过这些方法。

方法一:设置不同状态的缓存属性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')
          });
于 2017-03-15T17:58:56.307 回答
2

当您使用 gulp 时,您可以使用gulp-angular-templateCachegulp 插件来收集所有 html 文件,将它们连接成一个 javascript 文件并$templateCache根据文件路径将它们添加到 AngularJS 中。

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(参见我的入门),并且我使用的方法与 Midhun Darvin 的第 3 种方法(参见此处)相当,但requirejs我没有使用webpack. 但是,请记住,这种方法(使用requirejswebpack)将导致将 html 文件添加到包含 angularjs 代码的 javascript 文件中。这意味着对 javascript 文件的任何更改都会中断所有 html 文件的缓存,因为缓存破坏器将被更新。

于 2017-03-15T17:47:46.397 回答
0

我推荐一种类似于@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
     });
于 2019-12-18T19:15:54.673 回答