Angular 中 SwUpdate.activateUpdate() 的目的是什么?

Vil*_*kas 10 service-worker progressive-web-apps angular

Angular 文档提供了以下示例来激活软件更新:

constructor(updates: SwUpdate) {
  updates.available.subscribe(event => {
    if (promptUser(event)) {
        updates.activateUpdate().then(() => document.location.reload());
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

据我观察,调用本身不足以激活新版本,需要重新加载。然而document.location.reload(),即使没有activateUpdate()电话也足够了。

activateUpdate()打电话的目的是什么?为什么在重新加载就足够时调用它?

gka*_*pak 15

关于 Angular ServiceWorker 在幕后所做的一些背景:

  • 始终只有一个版本的软件,但它可以有多个版本的应用程序。
  • 它保留了客户端 ID到应用程序版本的映射,因此它知道为每个客户端提供哪个版本。
  • 当发现新版本时,它会下载它并将其标记为最新版本。
  • 从那时起,新客户端(例如新标签)将获得最新版本,但现有客户端(标签)仍将获得其先前分配的版本。

这种行为与 ServiceWorkers 通常的工作方式略有不同。它旨在允许向新客户提供最新版本,但不会破坏现有版本(通过向他们提供新内容,这些内容并非旨在与他们已经使用的旧 HTML/CSS/JS 代码一起使用)。


现在,回到activeUpdate()

这基本上告诉软件将最新版本分配给客户端。操作完成后,来自客户端的新请求将使用最新的应用程序版本提供服务。这并不安全,因此建议重新加载页面以确保所有代码都来自新版本。


仅仅重新加载就足够了吗?

这基本上取决于浏览器Client.id在重新加载时如何分配。如果浏览器在重新加载时为选项卡分配了一个新 ID,那么软件无论如何都会提供最新版本,因此swUpdate.activeUpdate()没有必要。另一方面,如果浏览器保持相同的客户端 ID,那么软件将提供没有swUpdate.activeUpdate().

目前,Chrome 似乎分配了一个新 ID(因此activeUpdate()在重新加载之前是不必要的)。我在SW 规范中找不到决定性东西,所以我不确定这是否符合规范以及是否所有浏览器都这样做。(也有可能浏览器过去的行为方式有所不同,因此activeUpdate()很有必要,但此后规范/浏览器已更新,如果您打算重新加载,则它变得多余。)


因此,如果您确认您支持的浏览器在这方面的行为符合预期,那么您无需activeUpdate()在重新加载之前调用。

请注意,文档示例只是可用 API 的简化说明。在真正的应用程序中,有多种方法可以处理更新(取决于应用程序的要求)。

例如,您可以:

  1. 立即激活更新(如果您确定您的应用可以处理)而不是重新加载。
  2. 显示更新可用的通知,并让用户单击以重新加载(从而更新)。
  3. 让应用知道有更新可用,并在下一次应用内导航时自动重新加载。(这就是我们在https://angular.io/ btw 中所做的。)

同样,并非所有策略都适用于所有类型的应用程序,因此请选择最适合您的策略。


编辑:
顺便说一句,如果您对如何改进文档有任何建议,请打开一个问题(或者最好提交一个拉取请求)!

  • 关于第一个问题,来自angular.io的相关代码是https://github.com/angular/angular/blob/8fbf40bf4000944c06458472142ca967ef8d3b1d/aio/src/app/sw-updates/sw-updates.service.ts,https:// /github.com/Angular/Angular/blob/8fbf40bf4000944c06458472142ca967ef8d3b1d/aio/src/app/shared/location.service.ts#L39 和 https://github.com/angular/angular/blob/8fbf40bf4000944c06458472142ca967ef8d3b1d /aio/src/应用程序/共享/location.service.ts#L49-L53。 (2认同)