检测单页应用程序中的应用程序版本更改

35

今天这里出现了一个问题,我没有一个明显的答案。

假设我们将所有资源文件(CSS和Javascript)连接并缩小,并在“主页”中声明它们。

在多页面应用程序中,如果CSS文件发生更改,则会在下一次完整页面加载时重新加载它。

在单页面应用程序中,用户可以持续工作数天,并且永远不会重新加载声明CSS文件的主页。 用户将永远看不到更改,直到发出Ctrl-F5。

我相信有人已经想到了这个问题,并有经验可以分享:)

对于我来说,使用WebSockets不是一个选项。首先,因为它过度使用,其次因为不是所有客户端都支持该技术。 对于所有WebSockets回退,同样的原因适用...我不会因此不停地访问我的服务器。

那么,有什么想法吗? :)

顺便说一下,如果需要特定解决方案,我们正在使用AngularJS。

谢谢!

3个回答

32

我曾经遇到过这个问题,我的解决方案很主观,并且可能不符合您的标准:

在打包我的前端应用程序和服务器应用程序时,我共享一个包含当前前端应用程序版本的配置文件。

前端:75%的路由隐式地调用Web服务(路由更改解析)。因此,每次调用服务器时,我都会包含自定义HTTP头(或GET / POST参数),其中包含前端应用程序的客户端版本。

服务器端:我将浏览器中用户的前端应用程序版本(上次用户刷新/加载SPA时加载的版本)与共享配置文件中的前端应用程序版本进行比较:

  • 如果版本匹配:我什么也不做。
  • 如果版本不匹配,则发送自定义的HTTP状态错误代码(例如418)

然后前端:我添加了一个响应拦截器,拦截任何418错误代码并强制刷新整个应用程序

就是这样。基本上,“检查”前端应用程序版本是否最新的事件是路由更改(通过ajax调用WS)。但是,您可以添加一些每5分钟左右调用专用WS的无限$ interval...

如果需要,我可以添加一些代码。

希望这有所帮助;)


我的最初想法是反过来做,让后端发送版本并在客户端上进行比较,但两种方法都存在一个共同的问题:我有多个独立版本的RESTful服务,并且对于特定的应用程序一无所知,因此它们永远无法验证这一点。尽管如此,在我写作时,我正在考虑可能应用程序特定的反向代理可以完成这项工作... - AlexCode
无限的 $timeout 转换为 WebSockets 或其回退,更具体地说是 Longpolling,但我不想在这里使用它。这不够频繁,不能持续地向服务器发送请求进行验证。 - AlexCode
是的,这里的选择取决于您的整个技术架构。顺便说一下,如果Websockets过于复杂和太新颖,您可以看看SSE(服务器发送事件:http://www.w3schools.com/html/html5_serversentevents.asp),它比socket.io轻得多(它是单向服务器->客户端推送)。 - Jscti
是的,有一些polyfills可用,但总是有更多或更少的限制。现在你有所有可能的选择 ;) - Jscti
所以我们现在采用了一种简化的解决方案。由于我们有一个“代理服务”,它(目前)是唯一与此应用程序交互的服务,我们在所有响应的HTTP头中添加了应用程序版本。如果我们收到更新版本,弹出窗口会通知用户并发出完整页面刷新...这种解决方案对于连接多个服务的应用程序不起作用,我并不完全同意它,但目前它可以使用。 - AlexCode
@Cétia:你好。你能否提供一些关于如何管理单页应用程序版本的建议或提示?我需要在服务器端手动添加版本号并在客户端检索吗?是否有自动化的方法可以解决这个问题? - balteo

2
我决定在这里补充我的最终想法:
我们目前采用了一种简化的解决方案。
由于我们有一个“代理服务”(目前为止)是唯一与该应用程序交互的服务,因此我们在所有响应的http标头中添加了应用程序版本。如果我们收到更新的版本,将会出现一个弹窗提示用户,并发出完整页面刷新...
对于没有自己的“私有”服务的应用程序,这个解决方案将无法使用。

1
我仍然找不到一个满意的解决方案。我在这里提出了我的问题,并提供了新的信息:https://softwareengineering.stackexchange.com/questions/423068/options-to-notify-users-single-page-application-spa-static-resources-have-upda - Qiulang

2
假设您正在使用AngularJS的路由功能,通过$route服务和提供程序,那么您可以使用$routeChangeSuccess事件来执行服务器请求,以便在需要更改的重大更改时进行处理;如果有任何更改,则可以使用window.location.reload()刷新页面并获取所有更新的资源和HTML。
以下过程可以根据您想要实现的方式进行更改:
1. 在您的服务器上设置一个配置文件,指示应用程序的版本。您还可以选择为不同的文件分配不同的版本,但由于您已经将所有资源文件连接起来,因此我想您可能会限制配置中的版本选项。
2. 创建一个包含所有必要信息(来自服务器的文件版本)和执行服务器请求以检查存储在服务中的当前文件版本的方法的服务。
3. 使用$routeChangeSuccess事件使用您在第2步中创建的服务执行服务器请求,如果请求返回有效确认存在更改,则通过window.location.reload()强制重新加载页面。

谢谢,伙计。我在Bixi的回答中最后一次回复解释了我们现在所做的事情。 - AlexCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接