Progressive
Web Apps
using the Angular Mobile Toolkit
Maxim Salnikov
-
Google Developer Expert in Angular
-
AngularJS Oslo Meetup organizer
-
Mobileera.Rocks 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
Progressive Web App
Progressive Web App (PWA) is a term used to denote a new software development methodology. Unlike traditional applications, Progressive Web App can be seen as an evolving hybrid of regular web pages (or websites) and a mobile application. This new application life-cycle model combines features offered by most modern browsers with benefits of mobile experience.
Websites timeline
Static
Dynamic
AJAX
RWD
PWA
PWA?
PWA?
- Progressive
- Discoverable
- Linkable
- App-like
- Responsive
- Connectivity-independent
- Re-engageable
- Installable
- Fresh
- Safe
Progressive
It has adapt to older browsers to deliver the best experience possible given the features that are available
By definition, a progressive web app must work on any device and enhance progressively, taking advantage of any features available on the user’s device and browser.
Discoverable and Linkable
A well-designed website should use the URI to indicate the current state of the application. This will enable the web app to retain or reload its state when the user bookmarks or shares the app’s URL.
Because a progressive web app is a website, it should be discoverable in search engines. This is a major advantage over native applications, which still lag behind websites in searchability.
Re-engageable
The app should be able to receive notifications when the app is not running.
Mobile app users are more likely to reuse their apps, and progressive web apps are intended to achieve the same goals through features such as push notifications.
Installable
Web app install banners give you the ability to let your users quickly and seamlessly add your web app to their home screen, making it easy to launch and return to your app.
A progressive web app can be installed on the device’s home screen, making it readily available.
Secure
HTTPS secures the connection between you and your users, ensuring your users information is protected and isn't tampered with.
Because a progressive web app has a more intimate user experience and because all network requests can be intercepted through service workers, it is imperative that the app be hosted over HTTPS.
Connectivity-independent
It should work in areas of low connectivity or offline.
The app must be capable of starting offline and still display useful information.
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
Service worker
Background data synchronization
Responding to resource requests from other origins
Receiving centralized updates to expensive-to-calculate data such as geolocation or gyroscope, so multiple pages can make use of one set of data
Client-side compiling and dependency management of CoffeeScript, less, CJS/AMD modules, etc. for dev purposes
Hooks for background services
Custom templating based on certain URL patterns
Performance enhancements, for example pre-fetching resources that the user is likely to need in the near future, such as the next few pictures in a photo album.
Service worker
Service workers essentially act as proxy servers that sit between web applications, and the browser and network (when available).
A service worker is an event-driven worker registered against an origin and a path
A service worker is run in a worker context
Service workers only run over HTTPS, for security reasons
Service worker
Register
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('Registration successful with scope: ', registration.scope);
}).catch(function(err) {
// registration failed :(
console.log('Registration failed: ', err);
});
}
Scope!
Install
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(URLS_TO_CACHE);
})
);
});
Files to cache!
Update
Update your SW file.
Your new service worker will be started and the install event will be fired.
At this point the old service worker is still controlling the current pages so the new service worker will enter a waiting state.
When the currently open pages (tabs) of your site are closed, the old service worker will be killed and the new service worker will take control.
Once your new service worker takes control, its activate event will be fired.
Update
self.addEventListener('activate', function(event) {
var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
Lifecycle
Intercepting requests
Involved APIs
-
Promises
-
Cache API
-
Fetch API
-
Notifications API
-
Push API
CanIUse?
Mobile Toolkit
Mobile Toolkit
ng new myApp --mobile
The --mobile flag has been disabled temporarily while we await an update
of angular-universal for supporting NgModule. Sorry for the inconvenience.
Mobile Toolkit
Mobile Toolkit
Mobile Toolkit
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>Proper Application Shell</h3>
</div>
<div class="md-progress-bar"></div>
<div class="signup-form">...</div>
</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 {}
Pre-fetching and caching
# First, install the Angular Service Worker
$ npm install --save @angular/service-worker
<script type="text/javascript">
// Require worker-basic.min.js copied to deploy directory from
// node_modules/@angular/service-worker/bundles
// Feature detection guards against older browsers that don't
// support service workers.
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/worker-basic.min.js');
}
</script>
Pre-fetching and caching
ngsw-manifest.json:
{
"static": {
"urls": {
"/index.html": "ae543...",
"/app.js": "9ff18...",
"/logo.png": "0e33a...",
...
}
}
}
import AngularSWPlugin from '@angular/service-worker/webpack';
webpack({
entry: 'index.html',
output: {...},
plugins: [
...,
new AngularSWPlugin()
]
});
Dynamic Caching
{
...,
"dynamic": {
"match": [{
"url": "/api",
"prefix": true,
"strategy": "fastest"
"invalidate": [...]
}]
}
}
Coming soon
Manifest
manifest.webapp
{
"name": "Hello Mobile",
"short_name": "Hello Mobile",
"icons": [
{
"src": "/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png",
"density": 0.75
},
...
],
"theme_color": "#000000",
"background_color": "#e0e0e0",
"start_url": "/index.html",
"display": "standalone",
"orientation": "portrait"
}
Push notifications
Backend
Push Service
Service worker
Push notifications
ngsw-manifest.json:
{
...,
"push": {
"showNotifications": true
}
}
manifest.webapp
{
...,
"gcm_sender_id": "12345"
}
Push notifications
# web-push package nicely handles details of pushing data
$ npm install --save web-push
const webPush = require('web-push');
webPush.setGCMAPIKey(...);
let payload = {
notification: {
title: 'Hello from the server', body: '...', icon: '/icon.png'
}
};
webPush.sendNotification({
payload: new Buffer(JSON.stringify(payload)), …
});
Push notifications
// Configure app to include module from @angular/service-worker
import {ServiceWorkerModule} 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
});
}
}
Mobile Toolkit
Hold On!
Thank you!
@webmaxru
Maxim Salnikov
Progressive Web Apps using the Angular Mobile Toolkit
By Maxim Salnikov
Progressive Web Apps using the Angular Mobile Toolkit
The term Progressive Web App refers to a group of technologies, such as service workers, and push notifications, that can bring native-like performance and user experience to web apps. Progressive Web Apps are interesting because in some ways they represent a coming of age for the Web. The Angular Mobile Toolkit makes it easy to build snappy Web apps that load instantly on any device, even without an internet connection. Take advantage of the searchability, shareability, and no-install-required-ability of the Web without compromise. During this 100% hands-on session we'll have a look on recent tools and guides from Angular team to help us build Progressive Web Apps. We'll have a look at Angular CLI and plugins/libraries for App Shell, Service Worker, and Application Manifest supporting us in fast and easy creation of installable, offline-capable, mobile-network-friendly apps. Agenda Introduction to PWA and Workshop Setup Introduction to Angular Mobile Toolkit Create an installable mobile web app with Angular CLI Make the App Installable with Web App Manifest App Shell Architecture Add an app shell component to the App Deep dive into Service Workers Add basic offline capabilities with Service Worker Adding Splash Screen Sending Push Notifications Questions and answers
- 2,643