KEMBAR78
PWA 與 Service Worker | PDF
PWA
& Service Worker Anna Su
1
Anna Su
PIXNET
2
About me
Why PWA?
What's PWA?
What's Service Workers
Making A Service Worker
3
Agenda
PWA
4
Why
5
What’s Wrong?
What’s Wrong with
Web ?
Slow mobile network
User-unfriendly
6
What’s Wrong with
Web ?
Slow mobile network
7
53% 3s
What’s Wrong with
Web ?
User-unfriendly
8
Splash Screen push notifications
What’s Wrong with
App ?
High cost
Difficultly share
9
What’s Wrong with
App ?
High cost
10
iOS WindowsAndroid
What’s Wrong with
App ?
Difficultly share
11
from Alex Russell in Chrome Dev Summit 2015
1
month
25 100+
App Web
What’s Wrong with
App ?
12
Alex Russell in Chrome Dev Summit 2015 ignite online & comScore
13
PWA
14
What’s
Progressive Web App
15
Reliable Fast EngagingReliable
What’s PWA ?
Reliable
16
What’s PWA ?
Fast
17
What’s PWA ?
Engaging
18
Chrome Dev Summit 2014
[github]
How does the PWA
looks like
19
20
Service Workers
21
What’s
22
What’s Service Workers ?
What’s Service Workers ?
23
24
What’s Service Workers ?
Service Workers
Lifecycle
25
Making
A
Service Worker
26
27
Making A Service Workers
design @Don
simple-pwa-demo
PWA To-Do List with Vanilla JS
(sw-precache)
(sw-precache-webpack-plugin)
PWA To-Do List with React/Redux
28
@Octocat
Making A Service Workers
code review -Jerry Hong
Getting Started with Service Workers
29
Registering the Service Worker
Setting up the Default Cache
Clearing Old Cache
Handling Fetch Requests
30
Making A Service Workers
31
Register install activate fetch
Making A Service Workers
Register
Registering the Service Worker
Registering the Service Worker
32
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
index.html
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.log('Error!', err));
}
</script>
33
Register install activate fetch
Making A Service Workers
Register
Service Worker Lifecycle
install activate fetch
Getting Started with Service Workers
34
// install
self.addEventListener('install', event => {
console.log('installing…');
});
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
});
// fetch
self.addEventListener('fetch', event => {
console.log('now fetch!');
});
sw.js
35
Register install activate fetch
Setting up the Default Cache
Making A Service Workers
Setting up the Default Cache
36
sw.js
const filesToCache = [
'/',
'/assets/images/btn_check.png',
'/assets/images/btn_del.png',
'/assets/images/ic_add.png',
'/assets/images/logo_todo.png',
'/src/main.css',
'/index.html'
];
const cacheName = 'todolist-v1';
Setting up the Default Cache
37
sw.js
// install
self.addEventListener('install', event => {
console.log('installing…');
event.waitUntil(
caches.open(cacheName).then(cache => {
// console.log('Caching app ok');
return cache.addAll(filesToCache);
})
);
});
// install
self.addEventListener('install', event => {
console.log('installing…');
event.waitUntil(
caches.open(cacheName).then(cache => {
// console.log('Caching app ok');
return cache.addAll(filesToCache);
})
);
});
// install
self.addEventListener('install', event => {
console.log('installing…');
event.waitUntil(
caches.open(cacheName).then(cache => {
// console.log('Caching app ok');
return cache.addAll(filesToCache);
})
);
});
// install
self.addEventListener('install', event => {
console.log('installing…');
event.waitUntil(
caches.open(cacheName).then(cache => {
// console.log('Caching app ok');
return cache.addAll(filesToCache);
})
);
});
// install
self.addEventListener('install', event => {
console.log('installing…');
event.waitUntil(
caches.open(cacheName).then(cache => {
// console.log('Caching app ok');
return cache.addAll(filesToCache);
})
);
});
38
Register install activate fetch
Clearing Old Cache
Making A Service Workers
`
39
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
event.waitUntil(
caches.keys().then(function(cacheNames) {
var promiseArr = cacheNames.map(function(item) {
if (item !== cacheName) {
// Delete that cached file
return caches.delete(item);
}
})
return Promise.all(promiseArr);
})
); // end e.waitUntil
});
sw.js
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
event.waitUntil(
caches.keys().then(function(cacheNames) {
var promiseArr = cacheNames.map(function(item) {
if (item !== cacheName) {
// Delete that cached file
return caches.delete(item);
}
})
return Promise.all(promiseArr);
})
); // end e.waitUntil
});
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
event.waitUntil(
caches.keys().then(function(cacheNames) {
var promiseArr = cacheNames.map(function(item) {
if (item !== cacheName) {
// Delete that cached file
return caches.delete(item);
}
})
return Promise.all(promiseArr);
})
); // end e.waitUntil
});
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
event.waitUntil(
caches.keys().then(function(cacheNames) {
var promiseArr = cacheNames.map(function(item) {
if (item !== cacheName) {
// Delete that cached file
return caches.delete(item);
}
})
return Promise.all(promiseArr);
})
); // end e.waitUntil
});
// activate
self.addEventListener('activate', event => {
console.log('now ready to handle fetches!');
event.waitUntil(
caches.keys().then(function(cacheNames) {
var promiseArr = cacheNames.map(function(item) {
if (item !== cacheName) {
// Delete that cached file
return caches.delete(item);
}
})
return Promise.all(promiseArr);
})
); // end e.waitUntil
});
40
Register install activate fetch
Handling Fetch Requests
Making A Service Workers
41
<script>
const list = document.getElementById('list');
// request
fetch('http://localhost:3000/people')
.then(res => {
return res.json();
})
.then(json => {
list.innerHTML = json
.map(item => `<li>${item.name}</li>`)
.join('');
})
</script>
index.html
Handling Fetch Requests
Handling Fetch Requests
42
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
sw.js
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(function(response) {
return response || fetch(event.request)
.then(res =>
caches.open(dataCacheName)
.then(function(cache) {
cache.put(event.request, res.clone());
return res;
})
);
})
);
});
43
44
Learn more?
45
46
47
48
49
50
PWA?
PWA?
Service Work
Registering the Service Worker
Setting up the Default Cache
Clearing Old Cache
Handling Fetch Requests
PWA To-Do List -
51
2017 iT
ref
https://huangxuan.me/pwa-qcon2016/#/
https://medium.com/lets-grow-business/why-
progressive-web-app-31dd11d9a925#.zb3d2m1jv
https://igniteonline.com.au/why-progressive-web-
apps-beat-native-apps-hands-down/
52
ref images
http://ninetailsfoxchan.deviantart.com/art/Sad-
Png-by-NFC-304044918
http://mrmen.wikia.com/wiki/File:Mr._All-
Goes_Wrong.PNG
https://goo.gl/022j4n
https://www.labnol.org/software/chrome-offline-
dinosaur-game/28781/
53
Thanks
54

PWA 與 Service Worker

  • 1.
  • 2.
  • 3.
    Why PWA? What's PWA? What'sService Workers Making A Service Worker 3 Agenda
  • 4.
  • 5.
  • 6.
    What’s Wrong with Web? Slow mobile network User-unfriendly 6
  • 7.
    What’s Wrong with Web? Slow mobile network 7 53% 3s
  • 8.
    What’s Wrong with Web? User-unfriendly 8 Splash Screen push notifications
  • 9.
    What’s Wrong with App? High cost Difficultly share 9
  • 10.
    What’s Wrong with App? High cost 10 iOS WindowsAndroid
  • 11.
    What’s Wrong with App? Difficultly share 11 from Alex Russell in Chrome Dev Summit 2015 1 month 25 100+ App Web
  • 12.
    What’s Wrong with App? 12 Alex Russell in Chrome Dev Summit 2015 ignite online & comScore
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
    Chrome Dev Summit2014 [github] How does the PWA looks like 19
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
    27 Making A ServiceWorkers design @Don
  • 28.
    simple-pwa-demo PWA To-Do Listwith Vanilla JS (sw-precache) (sw-precache-webpack-plugin) PWA To-Do List with React/Redux 28 @Octocat Making A Service Workers code review -Jerry Hong
  • 29.
    Getting Started withService Workers 29
  • 30.
    Registering the ServiceWorker Setting up the Default Cache Clearing Old Cache Handling Fetch Requests 30 Making A Service Workers
  • 31.
    31 Register install activatefetch Making A Service Workers Register Registering the Service Worker
  • 32.
    Registering the ServiceWorker 32 <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script> index.html <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(reg => console.log('SW registered!', reg)) .catch(err => console.log('Error!', err)); } </script>
  • 33.
    33 Register install activatefetch Making A Service Workers Register Service Worker Lifecycle install activate fetch
  • 34.
    Getting Started withService Workers 34 // install self.addEventListener('install', event => { console.log('installing…'); }); // activate self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); }); // fetch self.addEventListener('fetch', event => { console.log('now fetch!'); }); sw.js
  • 35.
    35 Register install activatefetch Setting up the Default Cache Making A Service Workers
  • 36.
    Setting up theDefault Cache 36 sw.js const filesToCache = [ '/', '/assets/images/btn_check.png', '/assets/images/btn_del.png', '/assets/images/ic_add.png', '/assets/images/logo_todo.png', '/src/main.css', '/index.html' ]; const cacheName = 'todolist-v1';
  • 37.
    Setting up theDefault Cache 37 sw.js // install self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( caches.open(cacheName).then(cache => { // console.log('Caching app ok'); return cache.addAll(filesToCache); }) ); }); // install self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( caches.open(cacheName).then(cache => { // console.log('Caching app ok'); return cache.addAll(filesToCache); }) ); }); // install self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( caches.open(cacheName).then(cache => { // console.log('Caching app ok'); return cache.addAll(filesToCache); }) ); }); // install self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( caches.open(cacheName).then(cache => { // console.log('Caching app ok'); return cache.addAll(filesToCache); }) ); }); // install self.addEventListener('install', event => { console.log('installing…'); event.waitUntil( caches.open(cacheName).then(cache => { // console.log('Caching app ok'); return cache.addAll(filesToCache); }) ); });
  • 38.
    38 Register install activatefetch Clearing Old Cache Making A Service Workers
  • 39.
    ` 39 // activate self.addEventListener('activate', event=> { console.log('now ready to handle fetches!'); event.waitUntil( caches.keys().then(function(cacheNames) { var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); // end e.waitUntil }); sw.js // activate self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); event.waitUntil( caches.keys().then(function(cacheNames) { var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); // end e.waitUntil }); // activate self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); event.waitUntil( caches.keys().then(function(cacheNames) { var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); // end e.waitUntil }); // activate self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); event.waitUntil( caches.keys().then(function(cacheNames) { var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); // end e.waitUntil }); // activate self.addEventListener('activate', event => { console.log('now ready to handle fetches!'); event.waitUntil( caches.keys().then(function(cacheNames) { var promiseArr = cacheNames.map(function(item) { if (item !== cacheName) { // Delete that cached file return caches.delete(item); } }) return Promise.all(promiseArr); }) ); // end e.waitUntil });
  • 40.
    40 Register install activatefetch Handling Fetch Requests Making A Service Workers
  • 41.
    41 <script> const list =document.getElementById('list'); // request fetch('http://localhost:3000/people') .then(res => { return res.json(); }) .then(json => { list.innerHTML = json .map(item => `<li>${item.name}</li>`) .join(''); }) </script> index.html Handling Fetch Requests
  • 42.
    Handling Fetch Requests 42 self.addEventListener('fetch',event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); sw.js self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request) .then(res => caches.open(dataCacheName) .then(function(cache) { cache.put(event.request, res.clone()); return res; }) ); }) ); });
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
    PWA? PWA? Service Work Registering theService Worker Setting up the Default Cache Clearing Old Cache Handling Fetch Requests PWA To-Do List - 51 2017 iT
  • 52.
  • 53.
  • 54.