In previous versions of the Angular service worker implementation, one of the config options was \"routing\"
. This can be seen in this unanswered SO question, was r
I just had to deal with this for several days, though I'm not using routes, just a non-root base href. I'll share the configuration that's working for me, which has at least a chance of working for routed apps, because I get my app whenever I try to use route/ngsw/state
to debug.
http(s)://<host>/route/index.html
"scope": "/route/",
"start_url": "/route/index.html",
"baseHref": "/route/",
"index": "/index.html",
...
"files": [
"/index.html",
"/*.js"
]
"/route/index.html"
"/route/index.html"
and "/route/main.js"
because of the baseHref, which match the keys under which they are hashed and are now actually cached./route/
, so it will a.) attempt to handle requests and b.) find them in its caches when you go offline.One of the things that made this so damn difficult was how many different ways to specify paths and bases there are, and that some are quite accommodating while others are very strict. If your deployment is broken, you can't actually use the built-in debugging, and you can't just turn on debug logging like with a sane module. The docs are incredibly sparse, especially compared to how well things like Directives and Templates are covered.
Still, this was 1000% easier to get working than any other solution I found.
Side note: If you use ServiceWorkerModule.register('ngsw-worker.js', { enabled: true })
and move "serviceWorker": true,
and "ngswConfigPath": "ngsw-config.json"
up to the general build options in angular.json instead of under the prod config, you don't have to wait 5 extra minutes for a prod build when debugging.
P.S. Props to OP's sleuthing which got my breakpoints in the right places.
TL;DR: I've identified at least two issues causing breakage in my case; you can use this build script for now to try my fix, and see the app work offline here. Further testing & pull requests needed.
While I've been unable to find a documented answer, here's what I've been able to find thus far, in stepping through the ngsw-worker.js
file, as well as reading the @angular/service-worker
commit history.
The new ServiceWorkerModule
approach to "routing" is to take any "navigation" request (i.e. a non-index route on the same domain), and re-run the handleFetch
method, but now pointing to the index.html
request (source). This should work fine, given an SPA should be able to redirect to the URL once it has retrieved its cached files for the index.
So the problems that are causing my site above to fail when offline must not be directly related to routing, and I've found 2 thus far. Correcting these with a workaround has allowed me to get my app working mostly as expected. With the repro steps in the original question, cityaq is now working, while I've reproduced the original, failing site at cityaq-sw-issue.
The issues:
Hosted versions of an Angular app, where the --base-href
flag is set from the CLI, list absolute URLs for their service worker resources. When comparing requests to these resources, ngsw-worker.js
is expecting relative URLs
baseHref
is getting included in the resource URLs when ngsw.json
is generated (source)Of the 3 available "states" that the ngsw-worker.js
can be in, in my experience, EXISTING_CLIENTS_ONLY
seems to bet set incorrectly.
ngsw-worker.js
will no longer attempt to retrieve cached resources (source), and in my testing under what seem to be "correct" circumstances, the app still enters this state even when the only change is removing an internet connectionWhile I put together a PR for issue #1, and wait for some help understanding issue #2, I'm using a workaround build script to modify ngsw-worker.js
after it's generated. Warning: it's ugly & definitely modifies the intended "safe" behavior of setting EXISTING_CLIENTS_ONLY
. However, for my app, it does allow correct offline performance both when running locally (http-server
), and deploying to a live URL (GitHub pages, in my case).
To use the workaround: (Angular 5, tested w/ Angular 5.2.1)
npm install replace-in-file --save-dev
build/fix-sw.js
package.json
:"scripts": {
...
"sw-build": "ng build --prod && node build/fix-sw",
"sw-build-live": ng build --prod --base-href https://your-url.com/ && node build/fix-sw"
...
}
npm run sw-build cd dist http-server -p 8080
npm run sw-build-live