Upload
others
View
18
Download
0
Embed Size (px)
Citation preview
in the #YearOfPWAin the #YearOfPWA
Maxim Salnikov@webmaxru
ProgressiveProgressiveAngular AppsAngular Apps
“ How to create AngularHow to create AngularProgressive Web App?Progressive Web App?
Using the native toolsUsing the native tools
Maxim SalnikovMaxim Salnikov
@webmaxru@webmaxru
Google Developer Expert, Microsoft MVPGoogle Developer Expert, Microsoft MVP
Angular Angular OsloOslo / / PWA OsloPWA Oslo meetups meetupsorganizerorganizer
ngVikingsngVikings / / Mobile Era Mobile Era conferencesconferencesorganizerorganizer
“ Products from the futureUI Engineer at ForgeRock
After all, what is PWA?After all, what is PWA?
Progressive web apps use modern web APIs alongwith traditional progressive enhancement strategyto create cross-platform web applications.
https://developer.mozilla.org/en-US/Apps/Progressive
After all, what is PWA?After all, what is PWA?
Progressive web apps use modern web APIs alongwith traditional progressive enhancement strategyto create cross-platform web applications.
https://developer.mozilla.org/en-US/Apps/Progressive
These apps work These apps work everywhereeverywhere and provide and provideseveral features that give them the sameseveral features that give them the sameuser experience advantagesuser experience advantages as native apps. as native apps.
UX advantages?UX advantages?
Smart networking + OfflineSmart networking + Offline
Staying notifiedStaying notified
UX advantages?UX advantages?
Smart networking + OfflineSmart networking + Offline
Staying notifiedStaying notified
Other cool thingsOther cool things
UX advantages?UX advantages?
Smart networking + OfflineSmart networking + Offline
Staying notifiedStaying notified
Other cool thingsOther cool things}} Service Worker
API
UX advantages?UX advantages?
Smart networking + OfflineSmart networking + Offline
Proper app experienceProper app experience
Staying notifiedStaying notified
Other cool thingsOther cool things}} Service Worker
API
Web App Manifest
Create Angular PWACreate Angular PWA
Code service worker Code service worker manuallymanually
Use framework-agnostic Use framework-agnostic PWA librariesPWA libraries
Create Angular PWACreate Angular PWA
Code service worker Code service worker manuallymanually
Use framework-agnostic Use framework-agnostic PWA librariesPWA libraries
Use Angular Service Worker (Use Angular Service Worker (NGSWNGSW))
Minimal PWAMinimal PWA
Served via HTTPSServed via HTTPS
Responsive, fast, cross-browserResponsive, fast, cross-browser
Minimal PWAMinimal PWA
Served via HTTPSServed via HTTPS
Responsive, fast, cross-browserResponsive, fast, cross-browser
App metadata providedApp metadata provided
Minimal PWAMinimal PWA
Served via HTTPSServed via HTTPS
Responsive, fast, cross-browserResponsive, fast, cross-browser
App metadata providedApp metadata provided
App loads while offlineApp loads while offline
Minimal PWAMinimal PWA
Served via HTTPSServed via HTTPS
Responsive, fast, cross-browserResponsive, fast, cross-browser
App metadata providedApp metadata provided
App loads while offlineApp loads while offline }} PWA schematicsPWA schematics
$ ng add @angular/pwa
$ ng build --prod
Apply PWA schematicsApply PWA schematics
ngsw-worker.jsngsw-worker.js
ngsw.jsonngsw.json
dist/project-namedist/project-name
$ ng add @angular/pwa
$ ng build --prod
Apply PWA schematicsApply PWA schematics
ngsw-worker.jsngsw-worker.js
ngsw.jsonngsw.json
dist/project-namedist/project-name
assets/icons/*.pngassets/icons/*.png
manifest.jsonmanifest.json
$ ng add @angular/pwa
$ ng build --prod
Apply PWA schematicsApply PWA schematics
ngsw-worker.jsngsw-worker.js
ngsw.jsonngsw.json
dist/project-namedist/project-name
safety-worker.jssafety-worker.js
assets/icons/*.pngassets/icons/*.png
manifest.jsonmanifest.json
worker-basic.min.jsworker-basic.min.js
App shell actionsApp shell actions
Generate assets Generate assets (+ hashes)(+ hashes) list list
Register service workerRegister service worker
App shell actionsApp shell actions
Generate assets Generate assets (+ hashes)(+ hashes) list list
Register service workerRegister service worker
Load and cache assetsLoad and cache assets
App shell actionsApp shell actions
Generate assets Generate assets (+ hashes)(+ hashes) list list
Register service workerRegister service worker
Load and cache assetsLoad and cache assets
Set up routingSet up routing
App shell actionsApp shell actions
Generate assets Generate assets (+ hashes)(+ hashes) list list
Register service workerRegister service worker
Load and cache assetsLoad and cache assets
Set up routingSet up routing
Serve assets from the Cache StorageServe assets from the Cache Storage
App shell actionsApp shell actions
Generate assets Generate assets (+ hashes)(+ hashes) list list
Register service workerRegister service worker
Load and cache assetsLoad and cache assets
Set up routingSet up routing
Serve assets from the Cache StorageServe assets from the Cache Storage
Load and cache the updated assetsLoad and cache the updated assets
NGSW configuration fileNGSW configuration file
ngsw-config.jsonngsw-config.json
{ "index": "/index.html", "assetGroups": [...], "dataGroups": [...] }
App shellApp shell
assetGroupsassetGroups
{ "name": "app", "installMode": "prefetch", "resources": {...} }
App shell resourcesApp shell resources
assetGroups / "app" / resourcesassetGroups / "app" / resources
"resources": { }
App shell resourcesApp shell resources
assetGroups / "app" / resourcesassetGroups / "app" / resources
"resources": { }
"files": [ "/favicon.ico", "/index.html", "/*.css", "/*.js" ]
Important!Important!
src/src/
assets/icons/*.pngassets/icons/*.png
manifest.jsonmanifest.json
index.html / <meta name="theme-color" ...>index.html / <meta name="theme-color" ...>
Important!Important!
src/src/
assets/icons/*.pngassets/icons/*.png
manifest.jsonmanifest.json
index.html / <meta name="theme-color" ...>index.html / <meta name="theme-color" ...>
To be customizedTo be customized
App shell / on-demandApp shell / on-demand
assetGroupsassetGroups
{ "name": "assets", "installMode": "lazy", "updateMode": "prefetch", "resources": {...} }
App shell / on-demandApp shell / on-demand
assetGroups / "assets" / resourcesassetGroups / "assets" / resources
"resources": { }
App shell / on-demandApp shell / on-demand
assetGroups / "assets" / resourcesassetGroups / "assets" / resources
"resources": { }
"files": [ "/assets/**" ],
App shell / on-demandApp shell / on-demand
assetGroups / "assets" / resourcesassetGroups / "assets" / resources
"resources": { }
"files": [ "/assets/**" ],
"urls": [ "https://fonts.googleapis.com/**", "https://fonts.gstatic.com/**" ]
Runtime cachingRuntime caching
dataGroupsdataGroups
{ "name": "api-freshness", "urls": [ "/api/breakingnews/**" ], }
Runtime cachingRuntime caching
dataGroupsdataGroups
{ "name": "api-freshness", "urls": [ "/api/breakingnews/**" ], }
"cacheConfig": { "strategy": "freshness", "maxSize": 10, "maxAge": "12h", "timeout": "10s" }
Runtime cachingRuntime caching
dataGroupsdataGroups
{ "name": "api-performance", "urls": [ "/api/archive/**" ], }
Runtime cachingRuntime caching
dataGroupsdataGroups
{ "name": "api-performance", "urls": [ "/api/archive/**" ], }
"cacheConfig": { "strategy": "performance", "maxSize": 100, "maxAge": "365d" }
Support API versioningSupport API versioning
dataGroupsdataGroups
{ "version": 1, "name": "api-performance", "urls": [ "/api/**" ], ... }
Support API versioningSupport API versioning
dataGroupsdataGroups
{ "version": 1, "name": "api-performance", "urls": [ "/api/**" ], ... }
{ "version": 2, "name": "api-performance", "urls": [ "/api/**" ], ... }
Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
updates.component.tsupdates.component.ts
Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
constructor(updates: SwUpdate) {}
updates.component.tsupdates.component.ts
Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
constructor(updates: SwUpdate) {}
this.updates.available.subscribe(event => { })
updates.component.tsupdates.component.ts
Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
constructor(updates: SwUpdate) {}
this.updates.available.subscribe(event => { })
updates.component.tsupdates.component.ts
if (confirm(`New Version is available! OK to refresh`)) { window.location.reload(); }
Push notificationsPush notifications
import { SwPush } from '@angular/service-worker';
push.component.tspush.component.ts
Push notificationsPush notifications
import { SwPush } from '@angular/service-worker';
constructor(push: SwPush) {}
push.component.tspush.component.ts
Push notificationsPush notifications
import { SwPush } from '@angular/service-worker';
constructor(push: SwPush) {}
subscribeToPush() { this.push.requestSubscription({ serverPublicKey: this.VAPID_PUBLIC_KEY }) .then(pushSubscription => { // Pass subscription object to the backend }) }
push.component.tspush.component.ts
Push notifications / sendPush notifications / send
{ "notification": { } }
server-side.js / sendNotification payloadserver-side.js / sendNotification payload
Push notifications / sendPush notifications / send
{ "notification": { } }
server-side.js / sendNotification payloadserver-side.js / sendNotification payload
"title": "Very important notification", "body": "Angular Service Worker is cool!", "icon": "https://angular.io/assets/logo.png", "actions": [ { "action": "gocheck", "title": "Go and check" } ], ...
Main available featuresMain available features
App shell withApp shell with
automatic updatesautomatic updates
Main available featuresMain available features
App shell withApp shell with
automatic updatesautomatic updatesRuntime data cachingRuntime data caching
Main available featuresMain available features
App shell withApp shell with
automatic updatesautomatic updatesRuntime data cachingRuntime data caching
Push notificationsPush notificationssubscription and displaysubscription and display
Main available featuresMain available features
App shell withApp shell with
automatic updatesautomatic updatesRuntime data cachingRuntime data caching
Push notificationsPush notificationssubscription and displaysubscription and display Debugger and kill switchDebugger and kill switch
ProsPros
Minimal PWA goesMinimal PWA goesout-of-the-boxout-of-the-box
Essential features areEssential features arecodelesscodeless
ConsCons
ProsPros
Minimal PWA goesMinimal PWA goesout-of-the-boxout-of-the-box
Essential features areEssential features arecodelesscodeless
Doing things inDoing things inAngular wayAngular way
ConsCons
ProsPros
Minimal PWA goesMinimal PWA goesout-of-the-boxout-of-the-box
Essential features areEssential features arecodelesscodeless
Doing things inDoing things inAngular wayAngular way
ConsCons
Intended to play a mainIntended to play a mainservice worker's role inservice worker's role inyour PWAyour PWA
ProsPros
Minimal PWA goesMinimal PWA goesout-of-the-boxout-of-the-box
Essential features areEssential features arecodelesscodeless
Doing things inDoing things inAngular wayAngular way
ConsCons
Intended to play a mainIntended to play a mainservice worker's role inservice worker's role inyour PWAyour PWA
There is no way to extendThere is no way to extendthe functionalitythe functionality
1700+ developers1700+ developers
bit.ly/go-pwa-slackbit.ly/go-pwa-slack
1700+ developers1700+ developers
Major browsers/frameworks/libs repsMajor browsers/frameworks/libs reps
bit.ly/go-pwa-slackbit.ly/go-pwa-slack