Skip to content

Spawning Web Worker from previous AppVersion results in network fallback #57971

@rozpuszczalny

Description

@rozpuszczalny

Which @angular/* package(s) are the source of the bug?

service-worker

Is this a regression?

Yes

Description

Consider the following scenario:

  • There is an existing Angular app with Service Worker
  • An angular app has an on-demand web worker, that is cached via Service Worker
  • A web worker is updated and a new version of an Angular app is deployed
  • Existing client received a new version of an Angular app, but did not refresh an already opened tab

In that scenario, when an existing client, that already received a new version of an Angular app, but did not refresh an already opened tab, triggers a code path, where a new Web Worker is created, a Web Worker script is fetched from the network, instead of from a cache. Because of the nature of deployment, scripts from a previous version are not stored on a server, meaning a request for an old Web Worker script results in a 404 error, and eventually in a Web Worker initialization failure.

I'd expect a Service Worker to serve a Web Worker script for an old version if a fetch is initiated from an old Angular app version.

Please use a minimal reproduction repository and follow the steps in the video to simulate the issue.

ngsw-web-worker.webm

Please provide a link to a minimal reproduction of the bug

https://github.com/rozpuszczalny/ngsw-web-worker

Please provide the exception or error you saw

Worker emitted an Event on 'error' callback; service worker called network, where it should use cache.

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 18.2.6
Node: 20.12.0
Package Manager: npm 10.5.0
OS: linux x64

Angular: 18.2.6
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
... service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1802.6
@angular-devkit/build-angular   18.2.6
@angular-devkit/core            18.2.6
@angular-devkit/schematics      18.2.6
@schematics/angular             18.2.6
rxjs                            7.8.1
typescript                      5.5.4
zone.js                         0.14.10

Anything else?

We are experiencing such an issue in our production setup, which makes an update process quite painful for the users. Weirdly, for some users, simply reloading a tab does not solve the issue - we have to instruct the users to manually delete a Service Worker via chrome://serviceworker-internals. We still didn't identify nor reproduce that scenario where reload is not working.


Probably introduced by #42607, which was first released with Angular v12.


A possible solution is to check if clientId and resultingClientId are both set. If that's true, clientId should be used over resultingClientId. My crude testing showed (at least in Chrome browser) that resultingClientId is the client ID of a newly created web worker, and clientId is the client ID of a tab that spawned a web worker.

Since resultingClientId is relevant when opening a new tab, I've tested and noticed that clientId is set to an empty string when opening a website in a separate tab. However, opening window.open('/', '_top') sets both clientId and resultingClientId - similar to a web worker scenario. Unfortunately, location.reload() also sets both clientId and resultingClientId, which further complicates a potential solution.

const clientId = event.resultingClientId || event.clientId;

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: service-workerIssues related to the @angular/service-worker package

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions