[Service Worker] Can't update sw if in SAFE_MODE
See original GitHub issueI’m submitting a…
[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
When the service worker is installed / initialized the first time, it fetches the ngsw.json
. If the content of ngsw.json
is not an valid json the sw goes into SAFE_MODE:
From thereon it is impossible to update the service worker. If you call SwUpdate.checkForUpdate()
it never resolves or rejects and no new fetch to ngsw.json
is performed due to the fact that messages are ignored in SAFE_MODE:
Replacing the wrong ngsw.json
with the correct one does only resolve this issue if:
- the service worker is unregistered (if
ngsw.json
did not contain json. for example it contains html) - or the sw is unregistered and the cache is cleared (if
ngsw.json
did contain a json. ex:{ "test": 123 }
). This also triggers the following error:Error: Invariant violated (initialize): latest hash null has no known manifest
This issue occurred on our firebase hosted app. It seems a cache sometimes returns a html page with a 2xx status instead of the ngsw.json
and broke our service worker. We also needed to clear the cache and unregister the service worker on some mobile clients. It might be that firebase sends sometimes a wrong json file or there might be another way to lock the service worker in the SAFE_MODE with latest hash null
error.
Expected behavior
- It should be possible to update the sw with
SwUpdate.checkForUpdate()
when the sw is in SAFE_MODE - Maybe the sw should try to refetch the
ngsw.json
? I’m not sure when and if this would be the appropriated way to handle this issue.
Minimal reproduction of the problem with instructions
Repo: https://github.com/sean-nicholas/test-angular-service-worker
- run
npm run build
cd
into `dist``- change the content of
ngsw.json
to- For non json case:
asdjknkfdnjgdfkaslkdm
- For json case:
{ "test": 123 }
- For non json case:
- run
http-server
(or something similar) indist
folder - goto localhost in incognito mode
- you get the error
- For non json case:
Unexpected token a in JSON at position 0
- For json case:
TypeError: Cannot convert undefined or null to object
- For non json case:
- sw installation fails and sw goes into SAFE_MODE
- reload & press the
Check for SW Update
Button Checking
will stay true and not fall back to false after a few ms- Replace the content of
ngsw.json
with the correct data
For non json case:
- Unregister the sw & reload -> it works again
For json case:
- Unregister the sw & reload
- Error:
Error: Invariant violated (initialize): latest hash null has no known manifest
occures Check for SW Update
seems to work but if you reload it fails (does not resolve) again- Clear the cache, unregister the sw & reload -> it works again
What is the motivation / use case for changing the behavior?
The service worker should not lock itself into a state were it can not be updated anymore.
Environment
"@angular/animations": "^5.2.4",
"@angular/cdk": "^5.2.0",
"@angular/common": "^5.2.4",
"@angular/compiler": "^5.2.4",
"@angular/core": "^5.2.4",
"@angular/forms": "^5.2.4",
"@angular/http": "^5.2.4",
"@angular/material": "^5.2.0",
"@angular/platform-browser": "^5.2.4",
"@angular/platform-browser-dynamic": "^5.2.4",
"@angular/router": "^5.2.4",
"@angular/service-worker": "^5.2.4"
Browser:
(Only tested in)
- [x] Chrome (desktop) version 64.0.3282.140
- [x] Chrome (Android) version 64.0.3282.137
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:8 (3 by maintainers)
I was just hit by this on my dev machine and had a hell of a time figuring out what happened. Unregistering the service worker wasn’t enough… had to unregister AND clear my cache in Chrome. If this were to ever affect an end user they wouldn’t stand a chance.
Im experiencing the same issue.
swUpdate.checkForUpdate()
promise never gets resolved/rejected, so that now i cannot trigger manually the refreshing in my app.My logic looks like this:
In this way i can make a button in my app which can be tapped by the user for check updates
checkForUpdates()
and it triggers thethis.swUpdate.available.subscribe(event => { ... }
which will open a snackbar. But currently its not possible due to the never resolving/rejecting promise. Am i right?UPDATE: Everything works fine, if i close chrome devtools! Opened devtools screws up service worker update mechanism. Check if you can manage to work sw update after closing devtools! Hope this helps