progressive angular apps - microsoft...after all, wha t is pwa? progressive web apps use modern web...

117
in the #YearOfPWA in the #YearOfPWA Maxim Salnikov @webmaxru Progressive Progressive Angular Apps Angular Apps

Upload: others

Post on 20-May-2020

16 views

Category:

Documents


0 download

TRANSCRIPT

in the #YearOfPWAin the #YearOfPWA

Maxim Salnikov@webmaxru

ProgressiveProgressiveAngular AppsAngular Apps

“ How to create AngularHow to create AngularProgressive Web App?Progressive Web App?

“ 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?

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.

#YearOfPWA#YearOfPWA

#YearOfPWA#YearOfPWA

Latest updatesLatest updates

Cross-platform?Cross-platform?

Cross-platform?Cross-platform?

BrowserBrowser

Cross-platform?Cross-platform?

BrowserBrowser

MobileMobile

Cross-platform?Cross-platform?

BrowserBrowser

DesktopDesktop

MobileMobile

Cross-platform?Cross-platform?

BrowserBrowser

DesktopDesktop

MobileMobile

Cross-platform?Cross-platform?

BrowserBrowser

DesktopDesktop

MobileMobile

Cross-platform?Cross-platform?

BrowserBrowser

DesktopDesktop

MobileMobile

OS

Cross-platform?Cross-platform?

BrowserBrowser

DesktopDesktop

MobileMobile

Flagged

OS

UX advantages?UX advantages?

UX advantages?UX advantages?

Smart networking + OfflineSmart networking + Offline

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

Create Angular PWACreate Angular PWA

Code service worker Code service worker manuallymanually

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))

Automate it!Automate it!

PWA MVPPWA MVP

Recipe #1Recipe #1

Minimal PWAMinimal PWA

Minimal PWAMinimal PWA

Served via HTTPSServed via HTTPS

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

Apply PWA schematicsApply PWA schematics

$ ng add @angular/pwa

Apply PWA schematicsApply PWA schematics

$ ng add @angular/pwa

$ ng build --prod

Apply PWA schematicsApply PWA 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

Running and auditingRunning and auditing

Running and auditingRunning and auditing

$ ng serve --prod

Running and auditingRunning and auditing

$ ng serve --prod

Running and auditingRunning and auditing

$ ng serve --prod

Running and auditingRunning and auditing

$ ng serve --prod

App shell actionsApp shell actions

 

App shell actionsApp shell actions

Generate assets Generate assets (+ hashes)(+ hashes) list list

 

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 configuration fileNGSW configuration file

ngsw-config.jsonngsw-config.json

{ "index": "/index.html", "assetGroups": [...], "dataGroups": [...] }

App shellApp shell

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/

Important!Important!

src/src/

manifest.jsonmanifest.json

Important!Important!

src/src/

assets/icons/*.pngassets/icons/*.png

manifest.jsonmanifest.json

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

Add more resources to theAdd more resources to theApp ShellApp Shell

Recipe #2Recipe #2

App shell / on-demandApp shell / on-demand

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/**" ]

Data requests cachingData requests caching

Recipe #3Recipe #3

Runtime cachingRuntime caching

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

Recipe #4Recipe #4

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/**" ], ... }

App update notificationsApp update notifications

Recipe #5Recipe #5

App version updatesApp version updates

v1v1

v1v1

ServerServer

BrowserBrowser

App version updatesApp version updates

v1v1 v2v2

v1v1

ServerServer

BrowserBrowser

App version updatesApp version updates

v1v1 v2v2

v1v1v1v1

ServerServer

BrowserBrowser

App version updatesApp version updates

v1v1 v2v2

v1v1v1v1 v2v2

ServerServer

BrowserBrowser

v2v2

App version updatesApp version updates

v1v1 v2v2

v1v1v1v1 v2v2

ServerServer

BrowserBrowser

v2v2

Notify about updatesNotify about updates

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(); }

Subscribing for the PushSubscribing for the Pushnotificationsnotifications

Recipe #6Recipe #6

Push notificationsPush notifications

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

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

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 ConsCons

 

ProsPros

Minimal PWA goesMinimal PWA goesout-of-the-boxout-of-the-box

ConsCons

 

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

 

bit.ly/go-pwa-slackbit.ly/go-pwa-slack

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

Thank you!Thank you!

Maxim Salnikov@webmaxru

Questions?Questions?