Maxim Salnikov
Angular GDE
How to create an Angular Progressive Web App?
Progressive web apps use modern web APIs along with traditional progressive enhancement strategy to create cross-platform web applications.
Dev builds
Service Worker
API
Web App Manifest
<script />
$ ng new myPWA --mobile$ ng new myPWA --service-worker$ ng new myPWA$ ng add @angular/pwa --project=myPWA$ ng build --prodNGSW 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=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"
}{
"version": 1,
"name": "api-performance",
"urls": [
"/api/**"
],
...
}{
"version": 2,
"name": "api-performance",
"urls": [
"/api/**"
],
...
}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()
})
})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"
}
],
...ng set apps.0.serviceWorker=false
ng build --prod
...deployrm dist/ngsw.json
...deploycp dist/safety-worker.js dist/ngsw-worker.js
...deployself.addEventListener('install', e => { self.skipWaiting(); });
self.addEventListener('activate', e => {
e.waitUntil(self.clients.claim());
self.registration.unregister().then(
() => { console.log('Unregistered old service worker'); });
});