Arvin
Progressive
Responsive
App-like
Fresh
Safe ( HTTPS )
Discoverable (manifest.json)
Re-engageable
Installable
Linkable
Four kinds of worker :
Web Workers provide a simple means for web content to run scripts in background threads.
Different scope with Window
Access global variable via Self
Can't manipulate DOM
Use postMessage() to communicate
importScripts();
(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ',registration.scope);
}).catch(function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
}
})();check your current service-worker: chrome://serviceworker-internals
const CACHE_NAME = 'my-site-cache-v1';
const urlsToCache = [
'/',
'/styles/main.css',
'/script/main.js'
];
self.addEventListener('install', (event) => {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});mdn: cache api
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
return fetch(event.request);
}
)
);
});mdn: fetch api
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
// IMPORTANT: Clone the request.
let fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
(response) => {
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// IMPORTANT: Clone the response.
let responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});Updating
self.addEventListener('activate', (e) => {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then((keyList) => {
return Promise.all(keyList.map((key) => {
console.log('[ServiceWorker] Removing old cache', key);
if (key !== cacheName) {
return caches.delete(key);
}
}));
})
);
});Progressive
Responsive
App-like
Fresh
Safe ( HTTPS )
Discoverable (manifest.json)
Re-engageable
Installable
Linkable
Have a nice Icon on homescreen
Full screen mode, no more url bar!
Control screen orientation。
Splash screen setting
Tracking your app open from app or url
{
"name": "REACT PWA",
"short_name": "REACT PWA",
"icons": [{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
}, {
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
}, {
"src": "images/touch/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "images/touch/icon-256x256.png",
"sizes": "256x256",
"type": "image/png"
}],
"start_url": "/",
"display": "standalone",
"background_color": "#3E4EB8",
"theme_color": "#2F3BA2"
}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React PWA</title>
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="PWA">
</head>
<body>
<div id='app'>
</div>
<script type="text/javascript" src="bundle.510aef2ba974480fc6df.js"></script></body>
</html>
Offline Web Applications (udacity)