在这种情况下,如何有效地确保所有客户端在我推到生产环境时重新加载?例如,我已经看到Evernote有一个弹出窗口,说请重新加载浏览器以获取最新版本的Evernote。我想做类似的事情...是否需要使用socket.io或sock.js,或者我错过了一些简单的方法来实现这一目标?
更新:AppCache在2015年夏季被弃用,因此以下内容不再是最佳解决方案。新的建议是使用Service Workers代替。然而,Service Workers目前仍处于实验阶段,在IE和Safari中支持不稳定(即:可能没有支持)。
或者,许多构建工具现在无缝地整合了缓存破坏和文件“版本控制”技术以解决OP的问题。在这个领域,WebPack可以说是当前的领导者。
这可能是使用HTML5的AppCache的一个好用例。
您可能希望将其中一些步骤自动化到部署脚本中,但是以下提供的代码可能会对您有所帮助。
首先,创建您的应用程序缓存清单文件。这也将使您能够在客户端的浏览器中缓存资源,直到您明确修改应用程序缓存清单文件的日期为止。
/app.appcache:
CACHE MANIFEST
#v20150327.114142
CACHE:
/appcache.js
/an/image.jpg
/a/javascript/file.js
http://some.resource.com/a/css/file.css
NETWORK:
*
/
#v20150327.114142
行的注释是我们向浏览器表明清单已更改并且应重新加载资源的方式。它可以是任何内容,只要该文件与以前的版本在浏览器中看起来不同即可。在应用程序中部署新代码时,应修改此行。也可以使用构建ID代替。<html manifest="/app.appcache"></html>
最后,您需要添加一些Javascript代码来检查应用程序缓存是否有任何更改,如果有的话,请采取相应措施。这里是一个Angular模块。对于这个问题,这里有一个原始的示例:
appcache.js:
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the latest hotness.
window.applicationCache.swapCache();
if (confirm('A new version of the application is available. Would you like to load it?')) {
window.location.reload();
}
}
else {
// Manifest didn't changed. Don't do anything.
}
}, false);
如果AppCache不能满足您的需求,一个更简单的解决方案是创建一个简单的API端点,返回当前构建ID或最后部署日期时间。您的Angular应用程序偶尔会访问此端点,并将结果与其内部版本进行比较,如果不同,则重新加载自身。
或者,您可以考虑使用实时重新加载脚本(示例),但是,在开发中非常有帮助,但我不确定在生产中使用实时/原地重载资产是否是一个好主意。
app-abcd23.js
。app.js?hash=abcd23
,但有些浏览器可能仍然使用缓存版本。socket.io
。你可以在html meta tag
和js
文件中定义你的版本号,如果不匹配,就弹出一个窗口告诉用户刷新。最近我也遇到了同样的问题。我通过将我的应用程序的构建号附加到我的js/css文件中来解决了这个问题。所有我的脚本和样式标签都是由一个常见的包含文件中的脚本包含的,因此在js/css文件路径的末尾添加“构建号”非常容易,就像这样
/foo/bar/main.js?123
这个 123 是我在同一个头文件中跟踪的数字。每当我想让客户端强制下载应用程序的所有 js 文件时,我都会将其递增。这使我能够控制何时下载新版本,但仍允许浏览器在第一次请求后利用缓存。直到我通过递增构建号来推送另一个更新为止。
这也意味着我可以拥有任意长的缓存过期标头。
window.replace(window.location.href + '?' + key)
在我的情况下,我不得不再次运行这条相同的代码,稍后一秒钟,就像这样
setTimeout( (window.replace(window.location.href + '?' + key))=> {} , 1000)
完整代码如下:
const reloadIfFilesChanged = (cnt: number = 0, manifest: IManifest) => {
try {
// will fail if window does not exist
if (cnt > 10) {
return;
}
const id = localStorage.getItem('id');
if (!id) {
localStorage.setItem('id', manifest.id);
} else {
if (id !== manifest.id) {
// manifest has changed fire reload
// and set new id
localStorage.setItem('id', manifest.id);
location.replace(window.location.href + '?' + manifest.id);
setTimeout(() => {
location.replace(window.location.href + '?' + manifest.id + '1');
}, 1000);
}
}
} catch (e) {
// tslint:disable-next-line:no-parameter-reassignment
cnt++;
setTimeout(() => reloadIfFilesChanged(cnt, manifest), 1000);
}
};
已弃用 此功能已从Web标准中删除。尽管某些浏览器仍可能支持它,但正在被淘汰。不要在旧项目或新项目中使用它。使用Service Workers代替。
- pmont