Nico Martin // nicomartin.ch
Nico Martin // nicomartin.ch
Nico Martin
Web- / Frontend Developer
@nic_o_martin
nicomartin.ch
Say Hello GmbH
@SayHelloGmbH
sayhello.ch
Nico Martin // nicomartin.ch
- what is a progressive web app?
- features and examples
- installable
- offline usage
- push notifications
- pwa and WordPress
- pwa and spa
- browser- / device-support
- discussion
Nico Martin // nicomartin.ch
what is a "progressive web app"?
a website
+
Nico Martin // nicomartin.ch
mobile / hybrid app
website / webapp
installable
has to be installed
can't be installed
open
progressive web app
full access to the device
no unique identifier
works offline
app store
instant updates
online only
growing number APIs
linkable
Nico Martin // nicomartin.ch
progressive web app
.../application.js
.../theme.js
.../plugin.js
serviceworker.js
Nico Martin // nicomartin.ch
installable
if (!'serviceWorker' in navigator){
console.log('serviceworker is not supported');
} else if (navigator.serviceWorker.controller) {
console.log('serviceworker already registered');
} else {
navigator.serviceWorker.register('/serviceworker.js', {
scope: '/'
}).then(function (reg) {
console.log('serviceworker registered');
});
}
application.js
needs to be https
empty serviceworker.js in the root folder
Nico Martin // nicomartin.ch
<head>
...
<link rel="manifest" href="/manifest.json">
</head>
{
name: "Meine App",
short_name: "MeineApp",
start_url: "./",
description: "Meine erste Progressive Web App",
theme_color: "#1d1d1b",
background_color: "#ffffff",
display: "standalone",
lang: "",
orientation: "any",
icons: [
{
src: "/path/to/app-icon-512x512.png",
type: "image/png",
sizes: "512x512"
}
],
}
manifest.json
installable
Nico Martin // nicomartin.ch
installable
Nico Martin // nicomartin.ch
offline usage
ERR_INTERNET_DISCONNECTED
Nico Martin // nicomartin.ch
offline usage
application Storage
service worker
Nico Martin // nicomartin.ch
offline usage
offline Storage
service worker
Nico Martin // nicomartin.ch
offline usage
const version = '20171127';
const offlinePage = 'offline/';
const staticCachePages = [
'/',
'/' + offlinePage
];
const key = 'HelloTheme';
const staticCacheName = `${key}-Static-${version}`;
self.addEventListener('install', event => {
// install offline pages
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(staticCachePages);
})
.then(function () {
return self.skipWaiting();
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys()
.then(keys => {
return Promise.all(
keys.map(key => {
if (key !== staticCacheName) {
return caches.delete(key);
}
})
);
})
);
});
self.addEventListener('fetch', event => {
let request = event.request;
let url = new URL(request.url);
// only deal with requests on the same domain.
if (url.origin !== location.origin) {
return;
}
//don't do anything if wp stuff
if (request.url.match(/wp-admin/) || request.url.match(/preview=true/)) {
return;
}
// If non-GET request, try the network first, fall back to the offline page
if (request.method !== 'GET') {
event.respondWith(
fetch(request)
.catch(error => {
return caches.match(offlinePage);
})
);
return;
}
if (request.mode === 'navigate' || request.mode === 'cors') {
// if HTML requests, try the network first (and update cache), fall back to the cache, finally the offline page
event.respondWith(
fetch(request)
.then(response => {
addToCache(request);
return response;
})
.catch(error => {
return caches.match(request)
.then(response => {
return response || caches.match(offlinePage);
});
})
);
} else {
// if non-HTML request, look in the cache first, fall back to the network
event.respondWith(
caches.match(request)
.then(response => {
if (response) {
return response;
} else {
addToCache(request);
return fetch(request);
}
})
);
}
const addToCache = function (request) {
return caches.open(staticCacheName)
.then(cache => {
return fetch(request)
.then(response => {
return cache.put(request, response);
});
});
};
});
serviceworker.js
Nico Martin // nicomartin.ch
push notifications
Nico Martin // nicomartin.ch
push notifications
- client has to agree
- encrypted "subscription ID" has to be stored on the server
-
messaging service: firebase
- server --> messaging service --> device
- sw listens to the push
- sw displays the notification
- sw can interact with the notification
Nico Martin // nicomartin.ch
push notifications
const pushLatestPush = self.registration.scope + 'wp-content/latest_push.json';
self.addEventListener('push', event => {
event.waitUntil(
// pushManager
registration.pushManager.getSubscription()
.then(function (subscription) {
// get latest data
return fetch(pushLatestPush)
.then(function (response) {
return response.json()
.then(function (data) {
// show Notification
return self.registration.showNotification(data.title, {
body: data.body,
badge: data.badge,
icon: data.icon,
image: data.image
});
})
})
})
);
});
self.addEventListener('notificationclick', event => {
const notification = event.notification;
const action = event.action;
if (action === 'close') {
notification.close();
} else {
event.waitUntil(
fetch(pushLatestPush)
.then(function (response) {
return response.json()
.then(function (data) {
if ('' !== data.redirect) {
clients.openWindow(data.redirect);
}
notification.close();
})
})
.catch(function (err) {
notification.close();
})
);
}
});
serviceworker.js
Nico Martin // nicomartin.ch
pwa and WordPress
MPA vs. SPA
multi page application single page application
built on the server built on the client
Nico Martin // nicomartin.ch
pwa and WordPress
Nico Martin // nicomartin.ch
pwa and WordPress
Does it work?
Yes
Does have some improvements?
Yes
Does it feel like a mobile app?
No
Nico Martin // nicomartin.ch
pwa and spa
Nico Martin // nicomartin.ch
pwa and spa
app.skateparkguide.ch
api.skateparkguide.ch
WP REST API
service worker
Nico Martin // nicomartin.ch
pwa and spa
Nico Martin // nicomartin.ch
browser- / device-support
Nico Martin // nicomartin.ch
browser- / device-support
iOS / Safari
in Development (since August 2017)
Microsoft / Edge
in Development
https://developer.microsoft.com/en-us/microsoft-edge/platform/status/serviceworker/
Nico Martin // nicomartin.ch
discussion
https://wpch.slack.com/
@nico
@nic_o_martin
Thank you!
WPZürich Progressive Web Apps
By Nico Martin
WPZürich Progressive Web Apps
- 1,009