如何在部署之后强制客户端重新加载?

我正在使用MEAN堆栈(mongo,express,angular和node)。 我每隔几天就会比较频繁地进行生产。 我担心的是我有时会更改客户端代码和API,我不想确保API与以前版本的客户端代码的向后兼容性。

在这种情况下,什么是确保所有客户重新加载时最有效的方法? 我已经看到,例如印象笔记有一个popup式的说,请重新加载浏览器的最新版本的Evernote的东西。 我想做类似的事情…我需要沿着socket.io或sock.js的path,还是我错过了简单的东西,有一个更简单的方法来实现这一点?

更新: AppCache已于2015年夏季弃用,因此下面不再是最佳解决scheme。 新的build议是使用服务人员 。 但是,在IE和Safari中,服务人员目前仍然是粗略的(可能不支持)实验。

另外,许多构build工具现在可以无缝集成caching清除和文件“版本控制”技术来解决OP问题。 WebPack可以说是目前这个领域的领导者。


这对于使用HTML5的AppCache可能是一个很好的用例

您可能希望将这些步骤中的某些步骤自动化到您的部署脚本中,但是这里有一些代码可能会帮助您入门。

首先,创build你的appcache清单文件。 这也将允许您在客户端的浏览器中caching资源,直到您显式修改appcache清单文件的date。

/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: * / 

app.appcache中 ,第#v20150327.114142行的注释是我们向浏览器指出清单已经更改,资源应该重新加载。 只要文件与以前版本的浏览器看起来不同,就可以是任何东西。 在您的应用程序中部署新代码期间,应该修改此行。 也可以使用构buildID。

其次,在要使用appcache的任何页面上,修改标题标签,如下所示:

 <html manifest="/app.appcache"></html> 

最后,你需要添加一些Javascript来检查appcache是​​否有任何变化,如果有的话,做一些事情。 这里是一个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不适合您的情况,那么更多的贫民窟解决scheme将创build一个简单的API端点,返回当前的构buildID或上次部署date时间。 您的Angular应用程序偶尔会碰到这个端点,并将结果与​​其内部版本进行比较,如果不同,则重新加载。

或者,您可能会考虑一个实时重新加载脚本( 示例 ),但是,尽pipe在开发中非常有帮助,但我不确定在生产环境中使用实时/就地重新加载资产有多好。

也许你可以添加哈希到你的客户端代码文件名。 例如app-abcd23.js
所以浏览器将重新加载文件,而不是从caching中获取。 或者你可以添加散列到url.eg app.js?hash=abcd23但是一些浏览器可能仍然使用caching版本。

我知道铁轨有资产pipe道来处理它,但我不熟悉MEAN堆栈 。 为此,应该有一些npm包。

我不认为这是真的有必要使用socket.io如果你想通知用户他们的客户代码是过时的。 你可以在html meta tagjs文件中定义你的版本,如果不匹配,显示一个popup框并告诉用户刷新。

  1. 尽量限制你的js /文件在更短的周期内,即:1天到期。
  2. 但是,如果你想要popup一些内容并告诉你的用户重新加载( ctrl + f5 )浏览器,那么只要创build一个脚本来popup这个消息,如果你只是改变了一些文件,标记刚才的ip / session重新加载/告诉重新加载,所以他们不会被多个popup窗口恼火。

我最近面临同样的问题。 我通过附加我的应用程序的内部版本号与我的js / css文件解决了这个问题。 我所有的脚本和样式标签都包含在一个通用的包含文件中,所以在js / css文件path的末尾添加一个“内部编号”是很简单的,就像这样

 /foo/bar/main.js?123 

这123是我跟踪在我的同一个头文件中的数字。 每当我希望客户端强制下载应用程序的所有js文件时,我都会增加它。 这使我可以控制下载新版本的时间,但仍然允许浏览器在第一个请求之后为每个请求使用caching。 这是直到我通过增加内部版本号推另一个更新。

这也意味着我可以有一个caching过期头,不pipe我想要多长时间。