Maxim Salnikov
Angular GDE
Products from the future
UI Engineer at ForgeRock
AJAX
Static
Dynamic
RWD
PWA
... Progressive Web App can be seen as an evolving hybrid of regular web pages (or websites) and a mobile application
... a new software development methodology
--mobile
v1.0.0-beta.8 - Experimental service worker by the Angular Mobile team
v0.1.0 - App Shell runtime library for Angular Progressive Web Apps
# First, install the Angular Service Worker
$ npm install --save @angular/service-worker
# Enable the SW registration + app shell in Angular CLI
$ ng set apps.0.serviceWorker=true
"apps": [
{
"serviceWorker": true
}
]
# NGSW works only in --prod mode
$ ng build --prod
<script src="sw-register.{HASH}.bundle.js"></script>
{
"static": {
"urls": {
"/index.html": "ae543...",
"/main.bundle.js": "9ff18...",
"/styles.bundle.css": "d6f44...",
"/assets/images/logo.png": "0e33a...",
...
}
}
}
{
"routing": {
"index": "/index.html",
"routes": {
"/": {
"prefix": false
},
"/some/routes-group-prefix": {
"prefix": true
}
}
}
}
{
"static" : {
...autogenerated
}
}
{
"routing" : {...}
...
}
Angular PWA
{
"external": {
"urls": [
{
"url": "https://fonts.gstatic.com/Roboto.ttf"
}
]
}
}
Angular PWA
{
"dynamic": {
"groups": [
{
"name": "api",
"urls": {...},
"cache": {...}
}
]
}
}
cache: {
"optimizeFor": "freshness", // or 'performance'
"networkTimeoutMs": 200,
"maxAgeMs": 1000,
"maxEntries": 2,
"strategy": "fifo" // or 'lru', 'lfu'
}
urls: {
"/api/breakingnews": {
"match": "prefix"
}
},
Angular PWA
import {NgServiceWorker} from '@angular/service-worker';
constructor(public sw: NgServiceWorker) {}
import {ServiceWorkerModule} from '@angular/service-worker'
imports: [
...
ServiceWorkerModule
]
sw.updates.subscribe(event => {
if (event.type === 'pending') {
// Ask user if they want to update?
if (agreeToUpdate) {
sw.activateUpdate(event.version);
}
} else {
// event.type === 'activation'
// NGSW is now serving a new version
location.reload();
}
});
Backend
Notification
Push Service
NGSW
App
Backend
Push Service
App
{
"push": {
"showNotifications": true,
"backgroundOnly": false
}
}
constructor(public sw: NgServiceWorker) {}
sw.registerForPush().subscribe(subscriptionObject => {
// Send subscription data to the server
});
import {NgServiceWorker} from '@angular/service-worker';
sw.push.subscribe(notificationPayload => {
// Process notification data
});
Angular PWA
import {bootstrapServiceWorker} from '@angular/service-worker/worker';
import {StaticContentCache} from '@angular/service-worker/plugins/static';
...
bootstrapServiceWorker({
manifestUrl: '/ngsw-manifest.json',
plugins: [
StaticContentCache(),
...
]
});
import {bootstrapServiceWorker} from '@angular/service-worker/worker';
import {StaticContentCache} from '@angular/service-worker/plugins/static';
...
import {MyCustomPlugin} from './plugins/my-custom-plugin';
bootstrapServiceWorker({
manifestUrl: '/ngsw-manifest.json',
plugins: [
StaticContentCache(),
...
MyCustomPlugin()
]
});
{
"static": {...},
"routing": {...},
"external": {...},
"dynamic": {...},
"push": {...}
}
Angular PWA