javascript 部署后如何强制客户端重新加载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29292051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force client reload after deployment?
提问by Andrew
I'm using the MEAN stack (mongo, express, angular and node). I'm deploying relatively frequently to production...every couple of days. My concern is that I'm changing the client side code and the API at times and I would rather not have to ensure backwards compatibility of the API with previous versions of the client code.
我正在使用 MEAN 堆栈(mongo、express、angular 和 node)。我相对频繁地部署到生产......每隔几天。我担心的是,我有时会更改客户端代码和 API,我宁愿不必确保 API 与以前版本的客户端代码向后兼容。
In such a scenario, what is the most effective way of ensuring that all clients reload when I push to production? I have seen that Evernote for example has a pop-up that says something along the lines of please reload your browser for the latest version of Evernote. I would like to do something similiar...do I need to go down the path of socket.io or sock.js or am I missing something simple and there is a simpler way to achieve this?
在这种情况下,确保所有客户端在我推送到生产时重新加载的最有效方法是什么?例如,我看到 Evernote 有一个弹出窗口,上面写着“请重新加载浏览器以获取最新版本的 Evernote”。我想做一些类似的事情......我是否需要沿着 socket.io 或 sock.js 的路径走下去,或者我错过了一些简单的东西并且有更简单的方法来实现这一点?
采纳答案by Marco Lüthy
Update:AppCache was deprecated summer 2015 so the below is no longer the best solution. The new recommendation is to use Service Workersinstead. However, Service Workers are currently still experimental with sketchy (read: probably no) support in IE and Safari.
更新:AppCache 已于 2015 年夏季弃用,因此以下不再是最佳解决方案。新的建议是改用Service Workers。然而,Service Workers 目前仍在试验 IE 和 Safari 中的粗略(阅读:可能没有)支持。
Alternatively, many build tools now seamlessly incorporate cache-busting and file "versioning" techniques to address OPs question. WebPackis arguably the current leader in this space.
或者,许多构建工具现在无缝地结合了缓存破坏和文件“版本控制”技术来解决 OP 问题。WebPack可以说是这个领域的当前领导者。
This might be a good use case for using HTML5's AppCache
这可能是使用 HTML5 的AppCache 的一个很好的用例
You'd probably want to automate some of these steps into your deployment scripts, but here is some code you might find useful to get you started.
您可能希望将其中一些步骤自动化到您的部署脚本中,但这里有一些代码,您可能会发现它们对您开始有用。
First, create your appcache manifest file. This will also allow you to cache resources in the client's browser until you explicitly modify the appcache manifest file's date.
首先,创建您的 appcache 清单文件。这也将允许您在客户端的浏览器中缓存资源,直到您明确修改 appcache 清单文件的日期。
/app.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:
*
/
In app.appcache, the comment on line #v20150327.114142
is how we indicate to the browser that the manifest has changed and resources should be reloaded. It can be anything, really, as long as the file will look different to the browser from the previous version. During deployment of new code in your application, this line should be modified. Could also use a build ID instead.
在app.appcache 中,在线注释#v20150327.114142
是我们如何向浏览器指示清单已更改并且应重新加载资源。它可以是任何东西,真的,只要文件在浏览器中看起来与以前的版本不同。在应用程序中部署新代码期间,应修改此行。也可以改用构建 ID。
Second, on any pages you want to use the appcache, modify the header tag as such:
其次,在您想要使用 appcache 的任何页面上,修改标题标记,如下所示:
<html manifest="/app.appcache"></html>
Finally, you'll need to add some Javascript to check the appcache for any changes, and if there are, do something about it. Here's an Angular module. For this answer, here's a vanilla example:
最后,您需要添加一些 Javascript 来检查 appcache 是否有任何更改,如果有,请对其进行处理。这是一个Angular 模块。对于这个答案,这是一个香草示例:
appcache.js:
应用缓存.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);
Alternatively, if AppCache won't work for your situation, a more ghetto solution would be to create a simple API endpoint that returns the current build ID or last deployment date-time. Your Angular application occasionally hits this endpoint and compares the result to it's internal version, and if different, reloads itself.
或者,如果 AppCache 不适用于您的情况,一个更简单的解决方案是创建一个简单的 API 端点,该端点返回当前构建 ID 或上次部署日期时间。您的 Angular 应用程序偶尔会访问此端点并将结果与其内部版本进行比较,如果不同,则重新加载自身。
Or, you may consider a live-reload script (example), but, while very helpful in development, I'm not sure how good of an idea it is to use live/in-place-reloading of assets in production.
或者,您可以考虑使用实时重新加载脚本(示例),但是,虽然对开发非常有帮助,但我不确定在生产中使用资产的实时/就地重新加载是多么好。
回答by at15
Maybe you can add hash to your client code file name. eg app-abcd23.js
.
So the browser will reload the file instead of get it from cache. or you can just add the hash to url.eg app.js?hash=abcd23
but some browser may still use the cached version.
也许您可以将哈希添加到您的客户端代码文件名中。例如app-abcd23.js
。
所以浏览器将重新加载文件而不是从缓存中获取它。或者您可以将哈希添加到 url.egapp.js?hash=abcd23
但某些浏览器可能仍会使用缓存版本。
i know rails has assets-pipline to handle it, but i am not familiar with MEAN stack. there should be some package in npm
for that purpose.
我知道 rails 有 assets-pipline 来处理它,但我不熟悉MEAN stack。npm
为此,应该有一些包。
And i dont think it is really necessary to use socket.io
if you want to notify the user their client code is out of date. you can define your version in both html meta tag
and js
file,if mismatch, show a popup and tell the user to refresh.
socket.io
如果您想通知用户他们的客户端代码已过期,我认为没有必要使用它。您可以在html meta tag
和js
文件中定义您的版本,如果不匹配,则显示一个弹出窗口并告诉用户刷新。
回答by Achshar
I was facing the same problem recently. I fixed this by appending my app's build number with my js/css files. All my script and style tags were included by a script in a common include files so it was trivial to add a 'build number' at the end of the js/css file path like this
我最近面临同样的问题。我通过在我的 js/css 文件中附加我的应用程序版本号来解决这个问题。我所有的脚本和样式标签都包含在一个通用包含文件中的脚本中,因此在 js/css 文件路径的末尾添加一个“内部版本号”是微不足道的,就像这样
/foo/bar/main.js?123
This 123 is a number that I keep track of in my same header file. I increment it whenever I want the client to force download all the js files of the app. This gives me control over when new versions are downloaded but still allows the browser to leverage cache for every request after the first one. That is until I push another update by increment the build number.
这个 123 是我在同一个头文件中跟踪的一个数字。每当我希望客户端强制下载应用程序的所有 js 文件时,我都会增加它。这让我可以控制何时下载新版本,但仍然允许浏览器在第一个请求之后利用缓存。直到我通过增加内部版本号来推送另一个更新。
This also means I can have a cache expiry header of however long I want.
这也意味着我可以拥有我想要的任何长度的缓存到期标头。
回答by rezashamdani
- Try to limit your js/files to expire within smaller periodic time, ie: 1 days.
- But in case you want something that pop-out and tell your user to reload (ctrl+f5) their browser, then simply make a script that popup that news if you just changed some of your files, mark the ip/session who have just reload/told to reload, so they will not be annoyed with multiple popup.
- 尝试限制您的 js/文件在更短的周期内过期,即:1 天。
- 但是,如果您想要弹出某些内容并告诉您的用户重新加载(ctrl+ f5)他们的浏览器,那么如果您刚刚更改了一些文件,只需制作一个弹出该新闻的脚本,标记刚刚重新加载的 IP/会话/被告知重新加载,因此他们不会因多个弹出窗口而烦恼。