Sam Beckham
@samdbeckham
How to make your web site load really, really fast, as a progressive web app.
<disclaimer>
</disclaimer>
– You, just now
Service worker
200 when offline
non-javascript content
https
http => https
Fast enough on 3g
Prompted to install the web app
Custom Splash Screen
Themed Address bar
<meta viewport> tag
Sized correctly for the viewport
❌ Service worker
❌ 200 when offline
✅ non-javascript content
✅ https
✅ http => https
✅ Fast enough on 3g
❌ Prompted to install the web app
❌ Custom Splash Screen
❌ Themed Address bar
✅ <meta viewport> tag
✅ Sized correctly for the viewport
<meta
name="viewport"
content="
width=device-width,
initial-scale=1
"
>
<meta name="viewport" content="width=device-width,initial-scale=1">
❌ Service worker
❌ 200 when offline
❌ Prompted to install the web app
❌ Custom Splash Screen
❌ Themed Address bar
✅ https
✅ http => https
✅ non-javascript content
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized correctly for the viewport
Browser
Server
request
response
Browser
Server
Service
Worker
Browser
Server
Service
Worker
cat-pic.png
cat-pic.png
Browser
Server
Service
Worker
cat-pic.png
if (navigator.serviceWorker) {
navigator.serviceWorker.register(
'/serviceWorker.js', {
scope: '/'
}
);
}
./scripts/main.js
self.addEventListener('install', event => {
// What do we want to do on install?
});
./serviceWorker.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('name-of-the-cache')
.then(cache => cache.addAll([
'/assets/scripts/main.js',
'/assets/scripts/forms.js',
'/assets/css/main.css',
'/index.html'
]))
);
});
./serviceWorker.js
self.addEventListener('fetch', event => {
// This is where the magic and
// the dragons live.
});
./serviceWorker.js
self.addEventListener('fetch', event => {
const request = event.request;
event.respondWith(
caches.match(request)
.then(response => {
return response || fetch(request)
})
);
});
./serviceWorker.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('name-of-the-cache')
.then(cache => cache.addAll([
'/assets/scripts/main.js',
'/assets/scripts/forms.js',
'/assets/css/main.css',
'/index.html'
]))
);
});
self.addEventListener('fetch', event => {
const request = event.request;
event.respondWith(
caches.match(request)
.then(response => response || fetch(request))
);
});
./serviceWorker.js
❌ Prompted to install the web app
❌ Custom Splash Screen
❌ Themed Address bar
✅ Service worker
✅ 200 when offline
✅ https
✅ http => https
✅ non-javascript content
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized correctly for the viewport
{
"name": "Frontend NE: The Conference",
"short_name": "Frontend NE",
"start_url": "/",
"scope": "/",
"display": "standalone",
"theme_color": "#4A4A4A",
"background_color": "#4A4A4A",
"icons": [{
"src": "/icon.png",
"sizes": "512x512",
"type": "image/png"
}]
}
./manifest.json
<head>
<!-- other head stuff -->
<link rel="manifest" href="/manifest.json">
</head>
./yourpage.html
❌ Prompted to install the web app
✅ Service worker
✅ 200 when offline
✅ https
✅ http => https
✅ Custom Splash Screen
✅ Themed Address bar
✅ non-javascript content
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized correctly for the viewport
✅ Service worker
✅ 200 when offline
✅ https
✅ http => https
✅ Prompted to install the web app
✅ Custom Splash Screen
✅ Themed Address bar
✅ non-javascript content
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized correctly for the viewport
Sam Beckham
@samdbeckham
Slides: https://goo.gl/SPFP1V