如何在发布新版本的 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
。但是,请记住,这种方法(使用 requirejs
或 webpack
)将导致 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
});
我目前 运行 在发布我的 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
。但是,请记住,这种方法(使用 requirejs
或 webpack
)将导致 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
});