I am following angular's best practice in order to make PWA.
After making production build (ng build --prod --aot
), I am also running the service worker from dist, on localhost
:
http-server -p 8080 -c-1 dist
When I am trying to sync the worker with my Angular, using:
navigator.serviceWorker.ready.then(function(swRegistration) {
console.log('swReady');
});
Nothing happens, and seems that SW is not communicating with Angular.
Working with a remote server (uploading dist) does work. So seems that the problem is dist not working with ng serve
.
What am I doing wrong?
It seems that currently we cannot use service worker with ng serve --prod
. However we can make a workaround.
We build the project ng build --prod
From the dist
location we take the ngsw-worker.js
and ngsw.json
files and copy them to the src
folder.
We modify our angular.json
file in order to serve them. We find the property "projects": {"[my-project-name]": {... "architect": {... "build": {... "options": {... "assets": [...
and there we add these two items – "src/ngsw-worker.js", "src/ngsw.json"
.
ng serve --prod
.I have reached till that point. The browser says that the SW is activated and running. The only consideration now is that if we change something in the SW, we need to rebuild again and make the same steps. But I believe we can develop more rapidly.
Good luck!
Note: this is based on Angular under Ionic. For plain Angular some paths are different (e.g. www -> dist) and 'ng' command should be used instead of 'ionic', so adjust accordingly.
Step 0. Add @angular/pwa, it will create service worker that is used in production (see any other instructions for that).
Step 1. Enable service worker use in debug build. Usually SW is enabled only for production, e.g. in file src/app/app.module.ts
, one of two implementations, change 'enabled' to true (or can alternatively add property 'useServiceWorker' to 'environment.ts' and 'environment.production.ts' files and set them both to 'true', later when debugging is done, will need to change to 'false' only the setting in environment.ts file):
imports: [ ...
- ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
+ ServiceWorkerModule.register('ngsw-worker.js', { enabled: true }),
],
or
imports: [ ...
ServiceWorkerModule.register('ngsw-worker.js'),
],
providers: [ ...
- { provide: SwRegistrationOptions, useFactory: () => ({ enabled: environment.production }) },
+ { provide: SwRegistrationOptions, useFactory: () => ({ enabled: true }) },
Step 2. Add some hooks to the 'scripts' in package.json
file. They are aimed at ensuring that all file hashes are correct in 'ngsw.json' file and SW could load files properly:
{
"scripts": { ...
+ "ionic:serve:before": "...(anything already there)... && echo {} > src/ngsw.json && cp www/ngsw.json src/ngsw.json",
+ "ionic:build:after":"...(anything already there)... && npm run ngsw:rebuild",
+ "postbuild": "...(anything already there)... && npm run ngsw:rebuild",
+ "ngsw:rebuild": "ngsw-config www ngsw-config.json && cp www/ngsw.json src/ngsw.json",
For ionic serve
to pick that file, it adds a blank file src/ngsw.json
in pre-build step and tries to copy calculated hashes from www folder. If 'ionic serve' fails, make sure to run 'ionic build' first. I know this step is iffy, but there are no better hooks e.g. in 'ng serve' - there are open feature requests for that.
Since 'src/ngsw.json' is created/generated, it should not be under source control/git, so add line '/src/ngsw.json' to '.gitignore' file.
Step 3. Add service worker source and config to your debug build. Add lines to file angular.json
that would copy 'ngsw-worker.js' and 'ngsw.json' to www/ (production build does it automatically, this will copy it during debug build):
{
"projects": {
"app": {
"architect": {
"build": {
"options": {
"assets": [
+ {
+ "glob": "ngsw-worker.js",
+ "input": "node_modules/@angular/service-worker",
+ "output": "."
+ },
+ "src/ngsw.json",
...
Step 4. Build debug version (ensures current hashes in ngsw.json) and then serve with HTTPS. 'ionic serve' has --ssl and --external options (--external allows opening app on e.g. a phone):
ionic build
ionic ssl generate ;# creates SSL certs in .ionic/ssl/: cert.pem and key.pem
ionic serve --external --ssl
Another option is to use any appropriate HTTP server, which can do SSL and proxy for single-page apps (SPA). Package 'http-server' does not work well when proxy and ssl options are mixed, so use e.g. 'local-web-server' instead:
npm install -g local-web-server
ws -p 8100 --cert .ionic/ssl/cert.pem --key ,ionic/ssl/key.pem --https --spa index.html --directory www
Step 5. Add certificate to your browser CA list. Use the following steps for Chrome (or google it for other browsers):
https://www.nullalo.com/en/chrome-how-to-install-self-signed-ssl-certificates/
Done! Open Chrome and navigate to https://localhost:8100, see console for loaded Service Worker. If there are any errors in console, retrace prior steps - frameworks change rapidly and something might be already different.
With Chrome, you can enable a flag for treating a specific host as if it is a secure origin, allowing service workers to work:
./chrome --unsafely-treat-insecure-origin-as-secure=http://your.insecure.site:8080
To launch chrome from the terminal, you do need to know the executable location. This will be system dependent. For MacOs:
open /Applications/Google\ Chrome.app/ --args --unsafely-treat-insecure-origin-as-secure=http://your.insecure.site:8080
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With