Maxim Salnikov
Angular GDE
How to create an Angular Progressive Web App?
... attempts to combine features offered by most modern browsers with the benefits of mobile experience
... web apps that use the latest web technologies.
Progressive
Discoverable
Linkable
App-like
Responsive
Connectivity-independent
Re-engageable
Installable
Fresh
Safe
App
Service worker
$ ng new myProgressiveApp --service-worker
$ ng build --prod
$ ng set apps.0.serviceWorker=true
$ npm install @angular/service-worker --save
node_modules/@angular...
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
...
@NgModule({
...
imports: [
...
]
})
export class AppModule { }
ServiceWorkerModule.register('/ngsw-worker.js',
{ enabled: environment.production }),
{
"index": "/index.html",
"assetGroups": [...],
"dataGroups": [...]
}
{
"name": "app",
"installMode": "prefetch",
"resources": {...}
}
"resources": {
}
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
],
"files": [
"/favicon.ico",
"/index.html"
],
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {...}
}
"resources": {
}
"files": [
"/assets/**"
],
"urls": [
"https://fonts.googleapis.com/**",
"https://fonts.gstatic.com/**"
]
{
"name": "api-freshness",
"urls": [
"/api/breakingnews/**"
],
}
"cacheConfig": {
"strategy": "freshness",
"maxSize": 10,
"maxAge": "12h",
"timeout": "10s"
}
{
"name": "api-performance",
"urls": [
"/api/archive/**"
],
}
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "365d"
}
import { SwPush } from '@angular/service-worker';
constructor(private swPush: SwPush) {}
subscribeToPush() {
this.swPush.requestSubscription({
serverPublicKey: this.VAPID_PUBLIC_KEY
})
.then(pushSubscription => {
// Pass subscription object to backend
})
}
{
"notification": {
}
}
"title": "Very important notification",
"body": "Angular Service Worker is cool!",
"icon": "https://angular.io/assets/logo.png",
"actions": [
{
"action": "gocheck",
"title": "Go and check"
}
],
...
import { SwUpdate } from '@angular/service-worker';
constructor(private swUpdate: SwUpdate) {}
this.swUpdate.available.subscribe(event => {
let snackBarRef = this.snackBar
.open('Newer version of the app is available', 'Refresh');
snackBarRef.onAction().subscribe(() => {
window.location.reload()
})
})
Every time the Angular service worker starts, it checks for updates to the app by looking for updates to the ngsw.json manifest.
this.swUpdate.available.subscribe(event => {});
this.swUpdate.checkForUpdate()
- OR -
NGSW Debug Info:
Driver state: NORMAL ((nominal))
Latest manifest hash: cd4716ff2d3e24f4292010c929ff429d9eeead73
Last update check: 9s215u
=== Version 34c3fd2361735b1330a23c32880640febd059305 ===
Clients: 7eb10c76-d9ed-493a-be12-93f305394a77
=== Version cd4716ff2d3e24f4292010c929ff429d9eeead73 ===
Clients: ee22d69e-37f1-439d-acd3-4f1f366ec8e1
=== Idle Task Queue ===
Last update tick: 4s602u
Last update run: 9s222u
Task queue:
Debug log:
ng set apps.0.serviceWorker=false
ng build --prod
...deploy
rm dist/ngsw.json
...deploy