Progressive
Web Apps
using the Angular Mobile Toolkit
Maxim Salnikov
-
Google Developer Expert in Angular
-
Angular Oslo meetup organizer
-
ngVikings conf organizer
Products from the future
UI Engineer at ForgeRock
Google Experts are a global network of experienced product strategists, designers, developers and marketing professionals actively supporting developers, startups and companies changing the world through web and mobile applications.
Google Developer
Experts
Websites timeline
Static
Dynamic
AJAX
RWD
PWA
Progressive Web App
... Progressive Web App can be seen as an evolving hybrid of regular web pages (or websites) and a mobile application...
PWA?
- Progressive
- Discoverable
- Linkable
- App-like
- Responsive
- Connectivity-independent
- Re-engageable
- Installable
- Fresh
- Safe
AppShell
Service
Worker
Manifest
Push
Service worker
-
Make the website function offline
-
Increase online performance by reducing network requests for certain assets
-
Provide a customized offline fallback experience
of PWA
Involved APIs
-
Promises
-
Cache API
-
Fetch API
-
Notifications API
-
Push API
-
IndexedDB API
CanIUse?
Mobile Toolkit
Mobile Toolkit
Mobile Toolkit
No more
flag
--mobile
(for the moment)
Mobile Toolkit
App Shell
App Shell
<html>
<body>
<app-root-component>
<h1>Loading...</h1>
</app-root-component>
</body>
</html>
<html>
<body>
<app-root-component>
<style>...</style>
<div class="md-header">
<h3>Angular2Paris</h3>
</div>
<div class="md-progress-bar"></div>
</app-root-component>
</body>
</html>
App Shell
<html>
<body>
<app-root-component>
<md-toolbar color="primary">
<span>{{title}}</span>
</md-toolbar>
<md-progress-bar mode="indeterminate"></md-progress-bar>
</app-root-component>
</body>
</html>
App Shell
<html>
<style>md-toolbar { display: flex; box-sizing: border-box;...</style>
<body>
<app-root-component _nghost-cb4a-1="">
<md-toolbar _ngcontent-cb4a-1="" color="primary" class="md-primary" ng-reflect-color="primary">
<div class="md-toolbar-layout">
<md-toolbar-row>
<span _ngcontent-cb4a-1="">Angular2Paris</span>
</md-toolbar-row>
</div>
</md-toolbar>
<md-progress-bar _ngcontent-cb4a-1="" aria-valuemax="100" aria-valuemin="0" mode="indeterminate" role="progressbar" _nghost-cb4a-3="" ng-reflect-mode="indeterminate" aria-valuenow="0"> <div _ngcontent-cb4a-3="" class="md-progress-bar-background"></div> <div _ngcontent-cb4a-3="" class="md-progress-bar-buffer"></div> <div _ngcontent-cb4a-3="" class="md-progress-bar-primary md-progress-bar-fill" ng-reflect-ng-style="[object Object]" style="transform:scaleX(0);"></div> <div _ngcontent-cb4a-3="" class="md-progress-bar-secondary md-progress-bar-fill"></div> </md-progress-bar>
</app-root-component>
</body>
</html>
App Shell
import { UniversalModule } from 'angular2-universal';
@NgModule({
bootstrap: [AppComponent],
imports: [
AppModule,
UniversalModule.withConfig({
...
}),
})
export class AppShellModule {}
platformUniversalDynamic()
.serializeModule(ShellModule)
.then(html => console.log(html));
App Shell
# Install app-shell utility from github.com/angular/mobile-toolkit
$ npm install --save @angular/app-shell
// App code
import {AppShellModule} from '@angular/app-shell';
// In NgModule used for Universal prerendering:
AppShellModule.prerender()
// At runtime:
AppShellModule.runtime()
App Shell
@Component({
selector: 'app-root-component',
template: `
<!-- Only show loading indicator in the shell -->
<loading-indicator *shellRender>
</loading-indicator>
<!-- Hide a dynamic view until runtime -->
<dynamic-view *shellNoRender>
</dynamic-view>
`
})
export class AppRootComponent {}
Service Worker
Service Worker
@angular/service-worker/bundles
@angular/service-worker/build
@angular/service-worker/companion
@angular/service-worker/worker
@angular/service-worker/plugins
Pre-fetching and caching
# 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
Pre-fetching and caching
ngsw-manifest.json:
{
"static": {
"urls": {
"/index.html": "ae543...",
"/app.js": "9ff18...",
"/logo.png": "0e33a...",
...
}
}
}
/**
* Gulp tasks that generates a basic Angular service worker manifest.
*/
gulpGenerateManifest()
gulpAddStaticFiles(files, options)
/**
* Webpack plugin that generates a basic Angular service worker manifest.
*/
AngularServiceWorkerPlugin(manifestFile, manifestKey)
Dynamic Caching
{
"optimizeFor": "performance", // try to respond as fast as possible
"refreshAheadMs": 300000, // refresh data if it's older than 5 min
"strategy": "lfu", // manage the cache by evicting the URLs using LFU
"maxEntries": 1000, // track 1,000 requests
"maxAgeMs": 86400000 // consider entries stale after 1 day
}
Coming soon
Companion
import {NgServiceWorker} from '@angular/service-worker';
constructor(public sw: NgServiceWorker) {
sw.log().subscribe(message => this.log.push(message));
}
this
.sw
.checkForUpdate()
.subscribe(res => {
this.result = JSON.stringify(res);
});
this
.sw
.ping()
.subscribe(res => {
this.result = JSON.stringify(res);
});
Worker
import {bootstrapServiceWorker} from '../bootstrap';
import {StaticContentCache} from '../../plugins/static';
import {RouteRedirection} from '../../plugins/routes';
import {Push} from '../../plugins/push';
bootstrapServiceWorker({
manifestUrl: '/ngsw-manifest.json',
plugins: [
StaticContentCache(),
RouteRedirection(),
Push(),
],
});
Push notifications
Backend
Push Service
Service worker
Push notifications
ngsw-manifest.json:
{
...,
"push": {
"showNotifications": true,
"backgroundOnly": false
}
}
Push notifications
import {NgServiceWorker} from '@angular/service-worker';
// Inject an API for communicating with the Angular service worker
export class PushService {
constructor(worker: NgServiceWorker) {
worker.registerForPush().subscribe(endpoint => {
// Send endpoint data to the server to complete registration
};
worker.push.subscribe(payload => {
// Process payload
});
}
}
Hold On!
Dank je!
@webmaxru
Maxim Salnikov
Progressive Web Apps using the Angular Mobile Toolkit
By Maxim Salnikov
Progressive Web Apps using the Angular Mobile Toolkit
Progressive Web Apps are the next big thing for the web. They combine the advantages of two platforms: searchability and shareability of the web with capabilities and performance of native mobile. As a result, web developers can use their favorite tools to build installable, re-engageable, connectivity independent apps, that can bring native-like performance and user experience. The Angular Mobile Toolkit makes it easy to get started building PWA. It’s developed to automate main routines and provide us with some nice tools to control the progressive app behavior. During this practical session, we'll have a look at Mobile Toolkit’s main components, and how they take our web app to the next level. With just some simple updates we’ll get installable, offline-capable, mobile-network-friendly Angular app re-engaging users by push-notifications.
- 3,757