It eventually happened: Progressive Web Applications took a worthy place in the modern web landscape, and there is no more need to convince developers why to go for performant, reliable, and engaging apps. Your Angular application is not the exception: adding PWA features is getting it to the next level of user experience. We have at least two very interesting options to get there. First, the native Angular Service Worker (NGSW) by Angular team, super-powered by Angular CLI and some extra ng-pwa-tools. Second, the all new framework-agnostic Workbox library by Google Chrome team. What's easier to set up for your Angular app? What has wider functionality? What's faster and more robust? Let's go exploring, coding and testing! You will have 100% full overview of these two approaches after my session, but the final decision is only yours!
Online version: https://slides.com/webmax/ngsw-workbox/
6. After all, what is PWA?After all, what is PWA?
Progressive web apps use modern web APIs along
with traditional progressive enhancement strategy
to create cross-platform web applications.
https://developer.mozilla.org/en-US/Apps/Progressive
7. After all, what is PWA?After all, what is PWA?
Progressive web apps use modern web APIs along
with traditional progressive enhancement strategy
to create cross-platform web applications.
https://developer.mozilla.org/en-US/Apps/Progressive
These apps workThese apps work everywhereeverywhere and provideand provide
several features that give them the sameseveral features that give them the same
user experience advantagesuser experience advantages as native apps.as native apps.
27. Create Angular PWACreate Angular PWA
Code service workerCode service worker manuallymanually
Use Angular Service Worker (Use Angular Service Worker (NGSWNGSW))
28. Create Angular PWACreate Angular PWA
Code service workerCode service worker manuallymanually
Use Angular Service Worker (Use Angular Service Worker (NGSWNGSW))
Go for someGo for some PWA librariesPWA libraries
29. Create Angular PWACreate Angular PWA
Code service workerCode service worker manuallymanually
Use Angular Service Worker (Use Angular Service Worker (NGSWNGSW))
Go for someGo for some PWA librariesPWA libraries
sw-precachesw-precache
30. Create Angular PWACreate Angular PWA
Code service workerCode service worker manuallymanually
Use Angular Service Worker (Use Angular Service Worker (NGSWNGSW))
Go for someGo for some PWA librariesPWA libraries
sw-precachesw-precache
43. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
44. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
Redirected requestsRedirected requests should be managedshould be managed
45. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
Redirected requestsRedirected requests should be managedshould be managed
Always creating a new version of cache and deletingAlways creating a new version of cache and deleting
the old one isthe old one is not optimalnot optimal
46. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
Redirected requestsRedirected requests should be managedshould be managed
Always creating a new version of cache and deletingAlways creating a new version of cache and deleting
the old one isthe old one is not optimalnot optimal
Control overControl over cache sizecache size is requiredis required
47. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
Redirected requestsRedirected requests should be managedshould be managed
Always creating a new version of cache and deletingAlways creating a new version of cache and deleting
the old one isthe old one is not optimalnot optimal
Control overControl over cache sizecache size is requiredis required
Cache invalidationCache invalidation for runtime caching is complexfor runtime caching is complex
48. In the real worldIn the real world
Can't addCan't add opaque responsesopaque responses directlydirectly
Redirected requestsRedirected requests should be managedshould be managed
Always creating a new version of cache and deletingAlways creating a new version of cache and deleting
the old one isthe old one is not optimalnot optimal
Control overControl over cache sizecache size is requiredis required
Cache invalidationCache invalidation for runtime caching is complexfor runtime caching is complex
......
52. In the real worldIn the real world
All kinds ofAll kinds of fallbacksfallbacks needed for the strategiesneeded for the strategies
53. In the real worldIn the real world
All kinds ofAll kinds of fallbacksfallbacks needed for the strategiesneeded for the strategies
There are more complex strategies likeThere are more complex strategies like Stale-While-Stale-While-
RevalidateRevalidate
54. In the real worldIn the real world
All kinds ofAll kinds of fallbacksfallbacks needed for the strategiesneeded for the strategies
There are more complex strategies likeThere are more complex strategies like Stale-While-Stale-While-
RevalidateRevalidate
Good to haveGood to have routingrouting
55. In the real worldIn the real world
All kinds ofAll kinds of fallbacksfallbacks needed for the strategiesneeded for the strategies
There are more complex strategies likeThere are more complex strategies like Stale-While-Stale-While-
RevalidateRevalidate
Good to haveGood to have routingrouting
Good to have the possibility to provide someGood to have the possibility to provide some extraextra
settingssettings for different resource groupsfor different resource groups
56. In the real worldIn the real world
All kinds ofAll kinds of fallbacksfallbacks needed for the strategiesneeded for the strategies
There are more complex strategies likeThere are more complex strategies like Stale-While-Stale-While-
RevalidateRevalidate
Good to haveGood to have routingrouting
Good to have the possibility to provide someGood to have the possibility to provide some extraextra
settingssettings for different resource groupsfor different resource groups
......
68. Generate a new Angular PWAGenerate a new Angular PWA
"Yesterday""Yesterday"
69. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA --service-worker
"Yesterday""Yesterday"
70. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA --service-worker
Angular CLI 1.6-1.7 Angular CLI 1.6-1.7
Angular Service Worker 5Angular Service Worker 5
"Yesterday""Yesterday"
71. Generate a new Angular PWAGenerate a new Angular PWA
TodayToday
72. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
TodayToday
73. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
TodayToday
$ ng add @angular/pwa
74. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
Angular CLI 6Angular CLI 6
TodayToday
$ ng add @angular/pwa
75. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
Angular CLI 6Angular CLI 6
Angular Service Worker 6Angular Service Worker 6
TodayToday
$ ng add @angular/pwa
76. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
Angular CLI 6Angular CLI 6
Angular Service Worker 6Angular Service Worker 6
Web App ManifestWeb App Manifest
TodayToday
$ ng add @angular/pwa
77. Generate a new Angular PWAGenerate a new Angular PWA
$ ng new myPWA
Angular CLI 6Angular CLI 6
Angular Service Worker 6Angular Service Worker 6
Web App ManifestWeb App Manifest
@Schematics@Schematics
TodayToday
$ ng add @angular/pwa
115. Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
updates.component.tsupdates.component.ts
116. Notify about updatesNotify about updates
import { SwUpdate } from '@angular/service-worker';
constructor(private swUpdate: SwUpdate) {}
updates.component.tsupdates.component.ts
117. Notify about updatesNotify about updates
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()
})
})
updates.component.tsupdates.component.ts
129. Kill switchKill switch
1.1. Long wayLong way
2.2. Short wayShort way
ng set apps.0.serviceWorker=false
ng build --prod
...deploy
rm dist/ngsw.json
...deploy
135. Main available featuresMain available features
App ShellApp Shell Runtime CachingRuntime Caching
Push NotificationsPush Notifications
136. Main available featuresMain available features
App ShellApp Shell Runtime CachingRuntime Caching
Push NotificationsPush Notifications Smart UpdatesSmart Updates
139. ProsPros
Smart defaults go outSmart defaults go out
of the boxof the box
Essential features areEssential features are
codelesscodeless
ConsCons
140. ProsPros
Smart defaults go outSmart defaults go out
of the boxof the box
Essential features areEssential features are
codelesscodeless
Doing things inDoing things in
Angular wayAngular way
ConsCons
141. ProsPros
Smart defaults go outSmart defaults go out
of the boxof the box
Essential features areEssential features are
codelesscodeless
Doing things inDoing things in
Angular wayAngular way
ConsCons
Intended to play aIntended to play a
main service worker'smain service worker's
role in your PWArole in your PWA
142. ProsPros
Smart defaults go outSmart defaults go out
of the boxof the box
Essential features areEssential features are
codelesscodeless
Doing things inDoing things in
Angular wayAngular way
ConsCons
Intended to play aIntended to play a
main service worker'smain service worker's
role in your PWArole in your PWA
There is no good wayThere is no good way
to extend theto extend the
functionalityfunctionality
167. Our own service workerOur own service worker
importScripts("workbox-v3.2.0/workbox-sw.js");
workbox.precaching.precacheAndRoute([])
my-serviceworker.jsmy-serviceworker.js
168. Our own service workerOur own service worker
importScripts("workbox-v3.2.0/workbox-sw.js");
workbox.precaching.precacheAndRoute([])
my-serviceworker.jsmy-serviceworker.js
// Features code
workbox.routing.registerRoute(
/(http[s]?://)?([^/s]+/)timeline/,
workbox.strategies.networkFirst()
)
...