What is the purpose of SwUpdate.activateUpdate() in Angular?

孤街醉人 提交于 2020-06-15 05:09:25

问题


Angular documentation provides following example to activate an SW update:

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

From what I observe, the call itself is not sufficient to activate new version, reload is necessary. However document.location.reload() is sufficient even without activateUpdate() call.

What is the purpose of activateUpdate() call? Why call it at all when reload suffice?


回答1:


Some background on what the Angular ServiceWorker does under the hood:

  • There is always one version of the SW, but it can have multiple versions of the app.
  • It keeps a mapping of [client IDs] to app versions, so it knows which version to serve to each client.
  • When a new version is found, it downloads it and marks it as the latest version.
  • From that point onwards, new clients (e.g. new tabs) will be served that latest version, but existing clients (tabs) will still get the previous version.

This behavior is a little different than how ServiceWorkers usually work. It is designed to allow serving the latest version to new clients, but not break existing ones (by serving them new content that is not designed to work with the older HTML/CSS/JS code they are using already).


Now, back to activeUpdate():

This basically tells the SW to set the client to the latest version. Once the operation completes, new requests from client will be served the latest app version. This is not safe, therefore it is recommended to reload the page to ensure that all code comes from the new version.


Does simply reloading suffice?

This basically depends on how browsers assign Client.id on reloads. If the browser assigns a new ID to the tab on reload, then the SW will serve the latest version anyway, so swUpdate.activeUpdate() is not necessary. IF, on the other hand, the browser keeps the same client ID, then the SW would serve the old version without swUpdate.activeUpdate().

Currently, Chrome seems to assign a new ID (and therefore activeUpdate() is unnecessary before reload). I couldn't find something conclusive in the SW spec, so I am not sure whether this is per the spec and whether all browsers do the same. (It is also possible that browsers used to behave differently in the past, making activeUpdate() necessary, but the spec/browsers have been updated since, making it redundant if you plan to reload.)


So, if you verify that your supported browsers behave as expected in that regard, then you don't need to call activeUpdate() before reloading.

Note that the documentation example is just a simplified illustration of the APIs that are available. In a real app, there are several ways to handle the update (depending on the app's requirements).

For example, you could:

  1. Activate the update immediatelly (if you are certain that your app can handle that) and not reload.
  2. Show a notification that an update is available and let the user click to reload (And thus update).
  3. Let the app know that an update is available and have it automatically reload on the next in-app navigation. (This is what we do in https://angular.io btw.)

Again, not all strategies are suitable for all types of apps, so choose the one that works best for you.


EDIT:
BTW, if you have suggestions on how the documentation could be improved, please open an issue (or better yet submit a pull request)!




回答2:


From the github code, what I understand is, an activateUpdate() will do a postMessage() to the service worker thread to let it know about the new data and status and once the promise has been resolved(service worker thread knows about it), then reload the page.

https://github.com/angular/angular/blob/7.2.11/packages/service-worker/src/update.ts#L57-L64

activateUpdate(): Promise<void> {
    if (!this.sw.isEnabled) {
      return Promise.reject(new Error(ERR_SW_NOT_SUPPORTED));
    }
    const statusNonce = this.sw.generateNonce();
    return this.sw.postMessageWithStatus('ACTIVATE_UPDATE', {statusNonce}, statusNonce);
}

https://github.com/angular/angular/blob/master/packages/service-worker/src/low_level.ts#LC105

postMessageWithStatus(type: string, payload: Object, nonce: number): Promise<void> {
    const waitForStatus = this.waitForStatus(nonce);
    const postMessage = this.postMessage(type, payload);
    return Promise.all([waitForStatus, postMessage]).then(() => undefined);
}


来源:https://stackoverflow.com/questions/55494181/what-is-the-purpose-of-swupdate-activateupdate-in-angular

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!