Sam Beckham
@samdbeckham
✅ Non-Javascript content
✅ https
✅ https redirect
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized for the viewport
❌ Custom splash screen
❌ Themed Address Bar
❌ Service Worker
❌ 200 When offline
❌ Prompted to install the web app
{
"name": "GitLab",
"short_name": "GitLab",
"display": "standalone",
"scope": "/",
"start_url": "/",
"theme_color": "#474D57",
"background_color": "#380D75",
"icons": [
{
"src": "/pwa_icon_512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
./manifest.json
<head>
<!-- other head stuff -->
<link rel="manifest" href="/manifest.json">
</head>
./yourpage.html
✅ Custom splash screen
✅ Themed Address Bar
❌ Service Worker
❌ 200 When offline
❌ Prompted to install the web app
Browser
Server
request
response
Browser
Server
Service
Worker
Browser
Server
Service
Worker
cat.png
cat.png
Cache
Browser
Server
Service
Worker
cat.png
cat.png
Cache
Browser
Server
Service
Worker
offline.html
Cache
Browser
Server
Service
Worker
issue
offline
Cache
issue
// Register a service worker if our
// browser allows it
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(
'/service_worker.js',
{ scope: '/'}
);
}
const CURRENT_CACHE = '<%= Gitlab.version %>_<%= Gitlab.revision %>';
const OFFLINE_PAGE = '/-/offline';
self.addEventListener('install', event => {
event.waitUntil(caches.open(CURRENT_CACHE)
.then(cache => cache.add(OFFLINE_PAGE)));
});
self.addEventListener('activate', event => {
event.waitUntil(
caches
.keys()
.then(cacheNames =>
Promise.all(
cacheNames.map(cache =>
cache !== CURRENT_CACHE ? caches.delete(cache) : Promise.resolve(),
),
),
),
);
});
self.addEventListener('fetch', event => {
const { request } = event;
const { method, mode } = request;
if (method === 'GET' && mode === 'navigate') {
event.respondWith(fetch(request).catch(() => caches.match(OFFLINE_PAGE)));
}
});
./service_worker.js
const CURRENT_CACHE = '<%= Gitlab.version %>_<%= Gitlab.revision %>';
const OFFLINE_PAGE = '/offline';
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(CURRENT_CACHE)
.then(cache => cache.add(OFFLINE_PAGE)
});
./service_worker.js
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames =>
Promise.all(
cacheNames.map(cache =>
cache !== CURRENT_CACHE ?
caches.delete(cache) : Promise.resolve()
))
));
});
./service_worker.js
self.addEventListener('fetch', event => {
const { request } = event;
const { method, mode } = request;
if (
method === 'GET' &&
mode === 'navigate') {
event.respondWith(
fetch(request).catch(() => (
caches.match(OFFLINE_PAGE)));
)
}
});
./service_worker.js
const CURRENT_CACHE = '<%= Gitlab.version %>_<%= Gitlab.revision %>';
const OFFLINE_PAGE = '/-/offline';
self.addEventListener('install', event => {
event.waitUntil(caches.open(CURRENT_CACHE)
.then(cache => cache.add(OFFLINE_PAGE)));
});
self.addEventListener('activate', event => {
event.waitUntil(
caches
.keys()
.then(cacheNames =>
Promise.all(
cacheNames.map(cache =>
cache !== CURRENT_CACHE ? caches.delete(cache) : Promise.resolve(),
),
),
),
);
});
self.addEventListener('fetch', event => {
const { request } = event;
const { method, mode } = request;
if (method === 'GET' && mode === 'navigate') {
event.respondWith(fetch(request).catch(() => caches.match(OFFLINE_PAGE)));
}
});
./service_worker.js
❌ 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
✅
✅ Custom Splash Screen
✅ Themed Address bar
✅ non-javascript content
✅ Fast enough on 3g
✅ <meta viewport> tag
✅ Sized correctly for the viewport
❌
Prompted to install the web app
Sam Beckham
@samdbeckham