我发布SPA的新版本时遇到了麻烦,因为浏览器正在缓存html模板。
我的SPA使用Angular 1.5,ocLazyload和ui-router。我已经配置了gulp任务来使用缓存清除技术(使用gulp-rev),并且它运行得很好,至少对于脚本和css文件。但是,当我们对html文件进行更改时,浏览器会继续加载旧版本。有时甚至用Ctrl + F5刷新页面并不能解决问题,并且它会一直显示旧版本的HTML。
此外,配置浏览器以不制作html文件的缓存是不可取的(特别是对于移动设备),因为html更改可能不会经常发生。
是否有任何好的解决方案可以解决此问题,只有在有新版本的文件时才能获取html文件?
提前致谢!
答案 0 :(得分:3)
我在一个项目中遇到过这个问题。我试过这些方法。
方法1:设置不同状态的缓存属性为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:向模板网址添加时间戳。
// 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')
});
答案 1 :(得分:2)
当你使用gulp时,你可以使用gulp-angular-templateCache
,它是一个gulp插件来收集你所有的html文件,将它们连接成一个单独的javascript文件并将它们添加到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文件都是通过一次调用来检索的。
另一种方法是将缓存破坏程序添加到html文件中,并更新该文件的所有用法以包含缓存破坏程序的哈希值。但我并不是这种方法的粉丝。
编辑:第一种方法是我在基于gulp的项目中使用的方法。然而,这些天我将AngularJS与Webpack一起使用(参见我的starter),我使用的方法与Midhun Darvin的第3种方法相当(见here),但我没有requirejs
使用webpack
而是requirejs
。但是,请记住,这种方法(使用webpack
或<div class="dropdown">
<select id="real_dropdown">
<option disabled="">Options</option>
<option value="long">Something super long in here</option>
<option value="short">Short</option>
</select>
</div>
<select id="width_tmp_select">
<option id="width_tmp_option"></option>
</select>
)将导致html文件被添加到包含angularjs代码的javascript文件中。这意味着对javascript文件的任何更改都会为所有html文件制作缓存,因为缓存存储器将被更新。
答案 2 :(得分: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
});