25. 오프라인 우선
백그라운드 이벤트 처리
어디가 오프라인? 비행기 안에서만?
가능한 한 언제나!
브라우저에 진짜 없던 것
브라우저 꺼도 web push 옵니다!
그러면서 웹 그대로!
웹 서버 업데이트가 곧 앱 업데이트! URL! 웹의 장점은 바로 거기에
Lie-Fi 시! 데이터 사용할 때도!
push, sync, geofenceenter, ..
26. 표준 현황
개발 현황
2015년 6월 네 번째 WD 그리고..
2016년 Service Worker 1 CR 계획
4.0 40+ 44 32+
Edge? Safari?
27. 동작의 기초가 되는 개념 들
Same origin 에서 동작
Registration 기반으로 동작 key는 URL scope!
Navigation 시 매칭되는 SW가 있으면 document가 control 됨
버전 관리를 위해 waiting worker, active worker 존재
31. 오프라인 with Service Worker!
fetch 이벤트
Navigation/Resource request
onfetch
Page
SW
Cache 캐시 match 시도
Match된 Response
클라이언트에 respond
IDB
new
Response({
status: 200,
body: { … }
})
33. 인스톨하기
var navigator.serviceWorker;
sw.register(scriptURL, { scope: scopeURL })
리소스 Pre-caching 하기
oninstall = e => { /* 여기서 캐시 */ };
fetch event 처리 하기
onfetch = e => { /* e.request에 대해 개발자 맘대로! */ };
Cache 관리
onactivate = e => { /* 안 쓰는 cache delete도 개발자의 몫 */ };
업데이트 w/ 24시간 룰
매 navigation 시 registration.update() functional event
34. “/assets/v1” /assets/v1/serviceworker.js
[ Registration map ]
Scope Script URL
Register
Page에서
// scope defaults to ‘/‘
var sw = navigator.serviceWorker;
sw.register(‘/assets/v1/serviceworker.js’)
.then(reg => {
console.log(‘success!’);
reg.installing.postMessage(‘Howdy from your installing page.’);
})
.catch(e => {
console.error(‘Installing the worker failed!:’, e);
});
35. “/bar” /bar/sw1.js
Var sw = navigator.serviceWorker;
① sw.register(‘/bar/sw1.js’, { scope: ‘/bar’ });
② sw.register(‘/foo/sw.js’, { scope: ‘/foo’ });
③ sw.register(‘/bar/sw2.js’, { scope: ‘/bar’ } );
[ Registration map ]
Scope Script URL
“/foo” /foo/sw.js
Register 복수개의 registration 생성 가능
Page에서
“/bar” /bar/sw2.js ③ Replace sw1
①
②
36. onactivate
SW
oninstall
onfetch
Register가 trigger하는 인스톨 과정
브라우저 internal
oninstall = e => {
// pre-cache, etc.
};
onactivate = e => {
// upgrade Cache, etc.
};
onfetch = e => {
// Not yet ready
};
Fetched sw script
Fetch sw script
Update①
Install②
Activate③
onfetch
onfetch = e => {
// Not yet ready
};
37. Pre-cache in oninstall
// sw.js – 인스톨 과정에서 pre-caching
self.addEventListener(‘install’, function(e) {
// 명시된 모든 리소스를 성공적으로 받아 캐시 해야만 인스톨 성공
e.waitUntil(
self.caches.open(‘shellResources’).then(function(cache) {
return cache.addAll([
‘/app.html’,
‘/assets/v1/base.css’,
‘/assets/v1/app.js’,
‘/assets/v1/logo.png’,
‘/assets/v1/intro_video.webm’
]);
});
});
38. Delete unused caches in inactivate
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
});
https://jakearchibald.com/2014/offline-cookbook/#on-activate
39. Do proxy in onfetch
self.addEventListener(‘fetch’, function(e) {
// 성공적으로 인스톨 되기 전까지는 fetch 이벤트 발생 안 함
// 모든 Cache 함수는 aync 하게 동작 함. 따라서 인터페이스가 promise로 디자인 됨
e.respondWith(
self.caches.match(e.request).catch(function() {
return fetch(e.request);
}).catch(function() {
return self.caches.match(‘/fallback.html’);
})
);
});
40. onfetch
sw.js
Cache
캐시 match 시도
Match된 response
클라이언트에 respond
“/” /sw.js
[ Registration map ]
Scope Script URL
“/foo” /foo/sw.js
Page Navigate https://example.com/index.html
fetch 이벤트
Scope matching
Run SW
클라이언트 Match (navigation)
41. onfetch
sw.js
Cache 캐시 match 시도
Match된 response
클라이언트에 respond
“/” /sw.js
[ Registration map ]
Scope Script URL
“/img” /img/sw.js
Page
Fetch “https://example.com/img/flower.png
fetch 이벤트
Control
Run SW
Subresource request
66. 참고자료
개념 이해
•Introduction to Service Worker
•Service Worker - first draft published
표준 리소스
•Nightly
API 사용 패턴
•The offline cookbook
•플랫폼 구현자 참고 문서
•GitHub
•Platinum Service Worker Elements
•Service Worker API MDN