è¯ãäžæ¥ãåéïŒ
ServiceWorkerAPIãšCacheAPIã®ããŸããŸãªäœ¿çšäŸãåãäžããJakeArchibaldã®åªããèšäºãOfflineCookbookãã®ç¿»èš³ã玹ä»ããŸãã
ã³ãŒããå€ããåèªãå°ãªãããããããã®ãã¯ãããžãŒã®åºæ¬ã«ç²ŸéããŠããããšãåæãšããŠããŸãã
æ £ããŠããªãå Žåã¯ãMDNããå§ããŠãæ»ã£ãŠããŠãã ãããããã¯ãç¹ã«ããžã¥ã¢ã«ã®ããã®ãµãŒãã¹ã¯ãŒã«ãŒã«é¢ããå¥ã®è¯ãèšäºã§ãã
ãã以äžã®åºæãªãã
ãã€ãªãœãŒã¹ãç¯çŽããŸããïŒ
ã¯ãŒã«ãŒã䜿çšãããšããã£ãã·ã¥ãšã¯ç¬ç«ããŠãªã¯ãšã¹ããåŠçã§ãããããåå¥ã«æ€èšããŸãã
æåã®è³ªåã¯ããã€ãªãœãŒã¹ããã£ãã·ã¥ããå¿ èŠããããã§ãã
äŸåé¢ä¿ãšããŠã€ã³ã¹ããŒã«ãããå Žå
ã¯ãŒã«ãŒã®å®è¡äžã«çºçããã€ãã³ãã®1ã€ã¯ãã€ã³ã¹ããŒã«ã€ãã³ãã§ãããã®ã€ãã³ãã¯ãä»ã®ã€ãã³ããåŠçããããã®æºåã«äœ¿çšã§ããŸããæ°ããã¯ãŒã«ãŒãã€ã³ã¹ããŒã«ãããŠããå€ãã¯ãŒã«ãŒã¯åŒãç¶ãããŒãžãæäŸãããããã€ã³ã¹ããŒã«ã€ãã³ããåŠçããŠãããŒãžãç Žæããããšã¯ãããŸãããã¹ã¿ã€ã«ãç»åãã¹ã¯ãªããããã³ãã¬ãŒãã®ãã£ãã·ã¥ã«
é©ããŠããŸã...äžè¬çã«ãããŒãžã§äœ¿çšãããéçãã¡ã€ã«ã«é©ããŠããŸãã
ãã€ãã£ãã¢ããªã±ãŒã·ã§ã³ã®åæããŠã³ããŒãã«å«ãŸããŠãããã¡ã€ã«ã®ããã«ã¢ããªã±ãŒã·ã§ã³ãæ©èœããªããã¡ã€ã«ã«ã€ããŠè©±ããŸãã
self.addEventListener('install', event => {
event.waitUntil(
caches.open('mysite-static-v3')
.then(cache => cache.addAll([
'/css/whatever-v3.css',
'/css/imgs/sprites-v6.png',
'/css/fonts/whatever-v8.woff',
'/js/all-min-v4.js'
// ..
]))
)
})
event.waitUntilã¯ãã€ã³ã¹ããŒã«ã®æéãšçµæã決å®ããçŽæãåãå ¥ããŸããçŽæãæåŠãããå Žåãã¯ãŒã«ãŒã¯ã€ã³ã¹ããŒã«ãããŸãããcaches.openãšcache.addAllã¯çŽæãè¿ããŸãããªãœãŒã¹ã®1ã€ã䜿çšã§ããªãå Žåã
cache.addAllã®åŒã³åºãã¯æåŠãããŸãã
äŸåé¢ä¿ãšããŠã§ã¯ãªãã€ã³ã¹ããŒã«ãããå Žå
ããã¯åã®äŸãšäŒŒãŠããŸããããã®å Žåãã€ã³ã¹ããŒã«ãå®äºããã®ãåŸ ããªããããã€ã³ã¹ããŒã«ã¯ãã£ã³ã»ã«ãããŸãããã²ãŒã ã®åŸã®ã¬ãã«ã®ãªãœãŒã¹ãªã©ãçŸåšå¿ èŠãšãããŠããªãå€§èŠæš¡ãªãªãœãŒã¹ã«
é©ããŠããŸãã
self.addEventListener('install', event => {
event.waitUntil(
caches.open('mygame-core-v1')
.then(cache => {
cache.addAll(
// 11-20
)
return cache.addAll(
// 1-10
)
})
)
})
ã¬ãã«11ã20ã®å Žåã¯cache.addAllpromiseãevent.waitUntilã«æž¡ããªããããæåŠãããå Žåã§ãã²ãŒã ã¯ãªãã©ã€ã³ã§å®è¡ãããŸãããã¡ãããæåã®ã¬ãã«ã®ãã£ãã·ã¥ã§çºçããå¯èœæ§ã®ããåé¡ã«æ³šæããããšãã°ã倱æããå Žåã¯ãã£ãã·ã¥ãå詊è¡ããå¿ èŠããããŸãã
ã¯ãŒã«ãŒã¯ãã€ãã³ãã®åŠçåŸãã¬ãã«11ã20ããã£ãã·ã¥ãããåã«åæ¢ã§ããŸããããã¯ããããã®ã¬ãã«ãä¿åãããªãããšãæå³ããŸããå°æ¥çã«ã¯ããã®åé¡ã解決ããããã«ã¯ãŒã«ãŒã«ããã¯ã°ã©ãŠã³ãèªã¿èŸŒã¿ã€ã³ã¿ãŒãã§ã€ã¹ã远å ããããæ ç»ãªã©ã®å€§ããªãã¡ã€ã«ãããŠã³ããŒããããããäºå®ã§ãã
çŽ Per ãïŒãã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯2018幎ã®çµããã«å®è£ ãããBackground FetchãšåŒã°ããŠããŸãããããããŸã§ã®ãšãããChromeãšOperaã§ã®ã¿æ©èœããŸãïŒCanIUseã«ãããš68ïŒ ïŒã
ã¢ã¯ãã£ããŒã·ã§ã³æ
å€ããã£ãã·ã¥ã®åé€ãšç§»è¡ã«é©ããŠããŸãã
æ°ããã¯ãŒã«ãŒãã€ã³ã¹ããŒã«ããŠå€ãã¯ãŒã«ãŒã忢ãããšãæ°ããã¯ãŒã«ãŒãã¢ã¯ãã£ãåãããã¢ã¯ãã£ãåã€ãã³ããåãåããŸããããã¯ããªãœãŒã¹ã眮ãæããŠå€ããã£ãã·ã¥ãåé€ããçµ¶å¥œã®æ©äŒã§ãã
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys()
.then(cacheNames => Promise.all(
cacheNames.filter(cacheName => {
// true, , ,
// ,
}).map(cacheName => caches.delete(cacheName))
))
)
})
ã¢ã¯ãã£ããŒã·ã§ã³äžã¯ããã§ãããªã©ã®ä»ã®ã€ãã³ãããã¥ãŒã«å ¥ãããããããã¢ã¯ãã£ããŒã·ã§ã³ãé·ããªããšãçè«çã«ã¯ããŒãžããããã¯ãããå¯èœæ§ããããŸãããããã£ãŠããã®ã¹ããŒãžã¯ãå€ãã¯ãŒã«ãŒã§ã¯å®è¡ã§ããªãããšã«å¯ŸããŠã®ã¿äœ¿çšããŠãã ããã
ã«ã¹ã¿ã ã€ãã³ããçºçãããšã
ãµã€ãå šäœããªãã©ã€ã³ã«ã§ããªãå Žåã«é©ããŠããŸãããã®å Žåãäœããã£ãã·ã¥ãããããŠãŒã¶ãŒã決å®ã§ããããã«ããŸããããšãã°ãYoutubeãããªãWikipediaããŒãžãFlickrã®ç»åã®ã£ã©ãªãŒãªã©ã§ãã
ãŠãŒã¶ãŒã«[åŸã§èªã]ãŸãã¯[ä¿å]ãã¿ã³ã衚瀺ããŸãããã¿ã³ãã¯ãªãã¯ããããããªãœãŒã¹ãååŸããŠãã£ãã·ã¥ã«æžã蟌ã¿ãŸãã
document.querySelector('.cache-article').addEventListener('click', event => {
event.preventDefault()
const id = event.target.dataset.id
caches.open(`mysite-article ${id}`)
.then(cache => fetch(`/get-article-urls?id=${id}`)
.then(response => {
// get-article-urls JSON
// URL
return response.json()
}).then(urls => cache.addAll(urls)))
})
ãã£ãã·ã³ã°ã€ã³ã¿ãŒãã§ã€ã¹ã¯ãã¯ãŒã«ãŒèªäœãšåãããã«ããŒãžã§äœ¿çšã§ããããããªãœãŒã¹ãç¯çŽããããã«ã¯ãŒã«ãŒãåŒã³åºãå¿ èŠã¯ãããŸããã
å¿çãåä¿¡ããŠââããé
ãŠãŒã¶ãŒã®ã¡ãŒã«ããã¯ã¹ãèšäºã®ã³ã³ãã³ããªã©ãé »ç¹ã«æŽæ°ããããªãœãŒã¹ã«é©ããŠããŸããã¢ãã¿ãŒãªã©ã®ãã€ããŒã³ã³ãã³ãã«ãé©ããŠããŸããããã®å Žåã¯æ³šæãå¿ èŠã§ãã
èŠæ±ããããªãœãŒã¹ããã£ãã·ã¥ã«ãªãå Žåã¯ããããã¯ãŒã¯ããååŸããŠã¯ã©ã€ã¢ã³ãã«éä¿¡ãããã£ãã·ã¥ã«æžã蟌ã¿ãŸãã
ã¢ãã¿ãŒãã¹ãªã©ã®è€æ°ã®URLãèŠæ±ããå Žåã¯ããªãªãžã³ã¹ãã¢ïŒãªãªãžã³-ãããã³ã«ããã¹ããããŒãïŒããªãŒããŒãããŒãããªãããã«ããŠãã ããããŠãŒã¶ãŒããã£ã¹ã¯é åãè§£æŸããå¿ èŠãããå Žåã¯ãæåã«ãã¹ãã§ã¯ãããŸãããäžèŠãªãªãœãŒã¹ã®åé€ã«æ³šæããŠãã ããã
self.addEventListener('fetch', event => {
event.respondWith(
caches.open('mysite-dynamic')
.then(cache => cache.match(event.request)
.then(response => response || fetch(event.request)
.then(response => {
cache.put(event.request, response.clone())
return response
})))
)
})
ã¡ã¢ãªãå¹ççã«äœ¿çšããããã«ãå¿çæ¬æã1åã ãèªã¿åããŸããäžèšã®äŸã§ã¯ãcloneã¡ãœããã䜿çšããŠå¿çã®ã³ããŒãäœæããŠããŸããããã¯ãã¯ã©ã€ã¢ã³ãã«å¿çãéä¿¡ããããããã£ãã·ã¥ã«æžã蟌ãããã«è¡ãããŸãã
æ°èŠæ§ã®ãã§ãã¯äž
ææ°ããŒãžã§ã³ãå¿ èŠãšããªããªãœãŒã¹ã®æŽæ°ã«é©ããŠããŸããããã¯ã¢ãã¿ãŒã«ãåœãŠã¯ãŸããŸãã
ãªãœãŒã¹ããã£ãã·ã¥ã«ããå Žåã¯ããã䜿çšããŸãããæ¬¡ã®ãªã¯ãšã¹ãã§æŽæ°ãååŸããŸãã
self.addEventListener('fetch', event => {
event.respondWith(
caches.open('mysite-dynamic')
.then(cache => cache.match(event.request)
.then(response => {
const fetchPromise = fetch(event.request)
.then(networkResponse => {
cache.put(event.request, networkResponse.clone())
return networkResponse
})
return response || fetchPromise
}))
)
})
ããã·ã¥éç¥ãåãåã£ããšã
Push APIã¯ãã¯ãŒã«ãŒãæœè±¡åãããã®ã§ããããã«ãããã¯ãŒã«ãŒã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã®ã¡ãã»ãŒãžã«å¿çããŠå®è¡ã§ããŸããããã«ãããã¯ãŠãŒã¶ãŒã«é¢ä¿ãªãçºçããŸãïŒãã©ãŠã¶ãŒã¿ããéããŠããå ŽåïŒãããŒãžã¯éåžžãç¹å®ã®ã¢ã¯ã·ã§ã³ãå®è¡ããããã®èš±å¯ãæ±ããèŠæ±ããŠãŒã¶ãŒã«éä¿¡ããŸãããã£ããã¡ãã»ãŒãžããã¥ãŒã¹ãã£ãŒããã¡ãŒã«ãªã©ãéç¥ã«äŸåããã³ã³ãã³ãã«
é©ããŠããŸãããªã¹ãå ã®ã¿ã¹ã¯ãã«ã¬ã³ããŒå ã®ããŒã¯ãªã©ã®ã³ã³ãã³ããåæããããã«ã䜿çšãããŸãã
çµæã¯ãã¯ãªãã¯ãããšå¯Ÿå¿ããããŒãžãéããšããéç¥ã§ãããã ããéç¥ãéä¿¡ããåã«ãªãœãŒã¹ãç¯çŽããããšãéåžžã«éèŠã§ãããŠãŒã¶ãŒã¯éç¥ãåä¿¡ãããšãªã³ã©ã€ã³ã«ãªããŸãããã¯ãªãã¯ãããšãªãã©ã€ã³ã«ãªãå¯èœæ§ãããããããã®æç¹ã§ã³ã³ãã³ãããªãã©ã€ã³ã§å©çšã§ããããšãéèŠã§ããTwitterã¢ãã€ã«ã¢ããªã¯ãããå°ãééã£ãŠããŸãã
ãããã¯ãŒã¯æ¥ç¶ããªãå ŽåãTwitterã¯éç¥é¢é£ã®ã³ã³ãã³ããæäŸããŸããããã ããéç¥ãã¯ãªãã¯ãããšåé€ãããŸãããããããªãã§ãã ããïŒ
次ã®ã³ãŒãã¯ãéç¥ãéä¿¡ããåã«ãã£ãã·ã¥ãæŽæ°ããŸãã
self.addEventListener('push', event => {
if (event.data.text() === 'new-email') {
event.waitUntil(
caches.open('mysite-dynamic')
.then(cache => fetch('/inbox.json')
.then(response => {
cache.put('/inbox.json', response.clone())
return response.json()
})).then(emails => {
registration.showNotification('New email', {
body: `From ${emails[0].from.name}`,
tag: 'new-email'
})
})
)
}
})
self.addEventListener('notificationclick', event => {
if (event.notification.tag === 'new-email') {
// , , /inbox/ ,
// ,
new WindowClient('/inbox/')
}
})
ããã¯ã°ã©ãŠã³ãåæãã
ããã¯ã°ã©ãŠã³ãåæã¯ãã¯ãŒã«ãŒã«å¯Ÿãããã1ã€ã®æœè±¡åã§ããããã«ããã1åéããŸãã¯å®æçãªããã¯ã°ã©ãŠã³ãããŒã¿åæãèŠæ±ã§ããŸãããŸãããŠãŒã¶ãŒãããç¬ç«ããŠããŸãããã ããèš±å¯ã®èŠæ±ã圌ã«éä¿¡ãããŸãããã€ããŒãªãœãŒã¹ã®æŽæ°ã«
é©ããŠããŸããéç¥ã宿çã«éä¿¡ããé »åºŠãé«ãããããããœãŒã·ã£ã«ãããã¯ãŒã¯ã®æ°ããã€ãã³ãããã¥ãŒã¹ãã£ãŒãã®æ°ããèšäºãªã©ããŠãŒã¶ãŒã«è¿·æããããŸãã
self.addEventListener('sync', event => {
if (event.id === 'update-leaderboard') {
event.waitUntil(
caches.open('mygame-dynamic')
.then(cache => cache.add('/leaderboard.json'))
)
}
})
ãã£ãã·ã¥ã®ä¿å
ãœãŒã¹ã¯äžå®éã®ç©ºãé åãæäŸããŸãããã®ã¹ããŒã¹ã¯ãããŒã«ã«ãšã»ãã·ã§ã³ãã€ã³ããã¯ã¹ä»ãããŒã¿ããŒã¹ããã¡ã€ã«ã·ã¹ãã ããããŠãã¡ãããã£ãã·ã¥ãªã©ããã¹ãŠã®ã¹ãã¬ãŒãžéã§å ±æãããŸãã
ã¹ãã¬ãŒãžãµã€ãºã¯åºå®ãããŠããããããã€ã¹ãšã¹ãã¬ãŒãžã®ç¶æ ã«ãã£ãŠç°ãªããŸããæ¬¡ã®ããã«ç¢ºèªã§ããŸãã
navigator.storageQuota.queryInfo('temporary').then(info => {
console.log(info.quota)
// : < >
console.log(info.usage)
// < >
})
ãã®ã¹ãã¬ãŒãžãŸãã¯ãã®ã¹ãã¬ãŒãžã®ãµã€ãºãå¶éã«éãããšããã®ã¹ãã¬ãŒãžã¯ãçŸæç¹ã§ã¯å€æŽã§ããªãç¹å®ã®ã«ãŒã«ã«åŸã£ãŠã¯ãªã¢ãããŸãã
ãã®åé¡ã解決ããããã«ãèš±å¯èŠæ±ãéä¿¡ããããã®ã€ã³ã¿ãŒãã§ãŒã¹ïŒrequestPersistentïŒãææ¡ãããŸããã
navigator.storage.requestPersistent().then(granted => {
if (granted) {
// ,
}
})
ãã¡ããããŠãŒã¶ãŒã¯ããã«å¯Ÿããèš±å¯ãäžããå¿ èŠããããŸãããŠãŒã¶ãŒã¯ãã®ããã»ã¹ã«åå ããŠããå¿ èŠããããŸãããŠãŒã¶ãŒã®ããã€ã¹ã®ã¡ã¢ãªããã£ã±ãã§ããã€ããŒããŒã¿ãåé€ããŠãåé¡ã解決ããªãå ŽåããŠãŒã¶ãŒã¯ã©ã®ããŒã¿ãä¿æããã©ã®ããŒã¿ãåé€ããããæ±ºå®ããå¿ èŠããããŸãã
ãããæ©èœããããã«ã¯ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã©ãŠã¶ã¹ãã¢ãåå¥ã®ã¢ã€ãã ãšããŠæ±ãå¿ èŠããããŸãã
ãªã¯ãšã¹ããžã®åç
ãã£ãã·ã¥ãããªãœãŒã¹ã®æ°ã¯é¢ä¿ãããŸãããã¯ãŒã«ãŒã¯ããã€ãäœã䜿çšããããæç€ºãããŸã§ããªãœãŒã¹ã䜿çšããŸããããªã¯ãšã¹ããåŠçããããã®ããã€ãã®ãã³ãã¬ãŒããæ¬¡ã«ç€ºããŸãã
çŸéã®ã¿
ããŒãžã®çŸåšã®ããŒãžã§ã³ã®éçãªãœãŒã¹ã«é©ããŠããŸãããªã¯ãšã¹ãã«å¿ããŠãªãœãŒã¹ãéä¿¡ã§ããããã«ããã«ã¯ãã¯ãŒã«ãŒã®ã»ããã¢ãããã§ãŒãºã§ãããã®ãªãœãŒã¹ããã£ãã·ã¥ããå¿ èŠããããŸãã
self.addEventListener('fetch', event => {
// ,
//
event.respondWith(caches.match(event.request))
})
ãããã¯ãŒã¯ã®ã¿
åæããŒã¿ãéGETãªã¯ãšã¹ããªã©ããã£ãã·ã¥ã§ããªããªãœãŒã¹ã«é©ããŠããŸãã
self.addEventListener('fetch', event => {
event.respondWith(fetch(event.request))
// event.respondWith
//
})
æåã«ãã£ãã·ã¥ã次ã«é害ãçºçãããšãããã¯ãŒã¯
ãªãã©ã€ã³ã¢ããªã±ãŒã·ã§ã³ã§ã®ã»ãšãã©ã®ãªã¯ãšã¹ãã®åŠçã«é©ããŠããŸãã
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
)
})
ä¿åããããªãœãŒã¹ã¯ãã£ãã·ã¥ããè¿ãããä¿åãããŠããªããªãœãŒã¹ã¯ãããã¯ãŒã¯ããè¿ãããŸãã
æéããã£ã人ã¯èª°ã§ãé£ã¹ãŸãã
äœã¡ã¢ãªããã€ã¹ã®ããã©ãŒãã³ã¹ãåäžãããããã«ãå°ããªãªãœãŒã¹ã«é©ããŠããŸãã
å€ãããŒããã©ã€ããã¢ã³ããŠã€ã«ã¹ãããã³é«éã€ã³ã¿ãŒãããæ¥ç¶ã®çµã¿åããã«ããããã£ãã·ã¥ããããŒã¿ããã§ãããããããããããã¯ãŒã¯ããããŒã¿ããã§ããããæ¹ãéããªããŸãããã ããããŒã¿ããŠãŒã¶ãŒã®ããã€ã¹ã«ä¿åãããŠããéã«ãããã¯ãŒã¯ããããŒã¿ãååŸããããšã¯ããªãœãŒã¹ã®æµªè²»ã§ãã
// Promise.race ,
// .
//
const promiseAny = promises => new Promise((resolve, reject) => {
// promises
promises = promises.map(p => Promise.resolve(p))
// ,
promises.forEach(p => p.then(resolve))
// ,
promises.reduce((a, b) => a.catch(() => b))
.catch(() => reject(Error(' ')))
})
self.addEventListener('fetch', event => {
event.respondWith(
promiseAny([
caches.match(event.request),
fetch(event.request)
])
)
})
çŽ ã¬ãŒã³ïŒããã§ããã®ç®çã§Promise.allSettledã䜿çšã§ããŸããããã©ãŠã¶ãŒã®ãµããŒãã¯80ïŒ ã§ãããŠãŒã¶ãŒã®-20ïŒ ã¯å€åå€ãããŸãã
æåã«ãããã¯ãŒã¯ã次ã«é害ãçºçããå Žåã¯ãã£ãã·ã¥
èšäºãã¢ãã¿ãŒããœãŒã·ã£ã«ãããã¯ãŒã¯äžã®ãã¥ãŒã¹ãã£ãŒãããã¬ãŒã€ãŒã®è©äŸ¡ãªã©ãé »ç¹ã«æŽæ°ããããµã€ãã®çŸåšã®ããŒãžã§ã³ã«åœ±é¿ãäžããªããªãœãŒã¹ã«é©ããŠããŸãã
ããã¯ãæ°ããã³ã³ãã³ãããªã³ã©ã€ã³ãŠãŒã¶ãŒã«æäŸããå€ãã³ã³ãã³ãããªãã©ã€ã³ãŠãŒã¶ãŒã«æäŸããŠããããšãæå³ããŸãããããã¯ãŒã¯ããã®ãªãœãŒã¹ã®èŠæ±ãæåããå Žåã¯ããã£ãã·ã¥ãæŽæ°ããå¿ èŠããããŸãã
ãã®ã¢ãããŒãã«ã¯1ã€ã®æ¬ ç¹ããããŸãããŠãŒã¶ãŒã«æ¥ç¶ã®åé¡ããããé ãå Žåã¯ããã£ãã·ã¥ããã³ã³ãã³ããå³åº§ã«ãã§ããããã®ã§ã¯ãªãããªã¯ãšã¹ããå®äºããã倱æããã®ãåŸ ã€å¿ èŠããããŸãããã®åŸ æ©ã¯éåžžã«é·ããªãå¯èœæ§ããããã²ã©ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«ãªããŸãã
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
)
})
æåã«ãã£ãã·ã¥ã次ã«ãããã¯ãŒã¯
é »ç¹ã«æŽæ°ããããªãœãŒã¹ã«é©ããŠããŸãã
ããã«ã¯ãããŒãžã2ã€ã®èŠæ±ãéä¿¡ããå¿ èŠããããŸãã1ã€ã¯ãã£ãã·ã¥çšã§ããã1ã€ã¯ãããã¯ãŒã¯çšã§ããã¢ã€ãã¢ã¯ããã£ãã·ã¥ããããŒã¿ãè¿ãããããã¯ãŒã¯ããããŒã¿ãåä¿¡ãããšãã«ãããæŽæ°ããããšã§ãã
æ°ããããŒã¿ïŒãã¬ãŒã€ãŒã®è©äŸ¡ãªã©ïŒãåãåã£ããšãã«çŸåšã®ããŒã¿ã眮ãæããããšãã§ããå ŽåããããŸãããããã¯å€§ããªã³ã³ãã³ãã§ã¯åé¡ããããŸããããã«ããããŠãŒã¶ãŒãçŸåšèªãã§ãããã®ãæäœããŠãããã®ãæ¶ããå¯èœæ§ããããŸãã
Twitterã¯ãã¹ã¯ããŒã«ãç¶æããªãããæ¢åã®ã³ã³ãã³ãã®äžã«æ°ããã³ã³ãã³ãã远å ããŸãããŠãŒã¶ãŒã«ã¯ãç»é¢ã®äžéšã«æ°ãããã€ãŒãã®éç¥ã衚瀺ãããŸããããã¯ãã³ã³ãã³ãã®ç·åœ¢é åºã®ãããã§å¯èœã§ãããã®ãã³ãã¬ãŒããã³ããŒããŠããã£ãã·ã¥ããã³ã³ãã³ããã§ããã ãæ©ã衚瀺ããWebããååŸããæ°ããã³ã³ãã³ãã远å ããŸããã
ããŒãžã®ã³ãŒãïŒ
const networkDataReceived = false
startSpinner()
//
const networkUpdate = fetch('/data.json')
.then(response => response.json())
.then(data => {
networkDataReceived = true
updatePage(data)
})
//
caches.match('/data.json')
.then(response => {
if (!response) throw Error(' ')
return response.json()
}).then(data => {
//
if (!networkDataReceived) {
updatePage(data)
}
}).catch(() => {
// , -
return networkUpdate
}).catch(showErrorMessage).then(stopSpinner)
ã¯ãŒã«ãŒã³ãŒãïŒ
ãããã¯ãŒã¯ã«ã¢ã¯ã»ã¹ããŠãã£ãã·ã¥ãæŽæ°ããŸãã
self.addEventListener('fetch', event => {
event.respondWith(
caches.open('mysite-dynamic')
.then(cache => fetch(event.request)
.then(response => {
cache.put(event.request, response.clone())
return response
}))
)
})
å®å šç¶²
ãã£ãã·ã¥ãšãããã¯ãŒã¯ãããªãœãŒã¹ãååŸããããšããŠå€±æããå Žåã¯ããã©ãŒã«ããã¯ãå¿ èŠã§ãããã¬ãŒã¹ãã«ããŒïŒç»åããããŒã«çœ®ãæããïŒã倱æããPOSTãªã¯ãšã¹ããããªãã©ã€ã³ã§ã¯äœ¿çšã§ããŸãããããŒãžã«
é©ããŠããŸãã
self.addEventListener('fetch', event => {
event.respondWith(
//
// ,
caches.match(event.request)
.then(response => response || fetch(event.request))
.catch(() => {
// ,
return caches.match('/offline.html')
//
// URL
})
)
})
ããŒãžãã¡ãŒã«ãéä¿¡ããå Žåãã¯ãŒã«ãŒã¯éä¿¡ããåã«ã€ã³ããã¯ã¹ä»ãããŒã¿ããŒã¹ã«ä¿åããéä¿¡ã倱æããããšãããŒãžã«éç¥ã§ããŸãããã¡ãŒã«ã¯ä¿åãããŸããã
ã¯ãŒã«ãŒåŽã§ããŒã¯ã¢ãããäœæãã
ãµãŒããŒåŽã§ã¬ã³ããªã³ã°ããããã£ãã·ã¥ã§ããªãããŒãžã«é©ããŠããŸãã
ããŒãžã®ãµãŒããŒåŽã¬ã³ããªã³ã°ã¯éåžžã«é«éãªããã»ã¹ã§ãããã¬ã³ããªã³ã°ããšã«ç°ãªãå¯èœæ§ããããããåçã³ã³ãã³ãããã£ãã·ã¥ã«ä¿åããŠãæå³ããããŸãããããŒãžãã¯ãŒã«ãŒã«ãã£ãŠå¶åŸ¡ãããŠããå Žåã¯ããªãœãŒã¹ãèŠæ±ããŠããã®å Žã§ããŒãžãã¬ã³ããªã³ã°ã§ããŸãã
import './templating-engine.js'
self.addEventListener('fetch', event => {
const requestURL = new URL(event.request.url)
event.respondWith(
Promise.all([
caches.match('/article-template.html')
.then(response => response.text()),
caches.match(`${requestURL.path}.json`)
.then(response => response.json())
]).then(responses => {
const template = responses[0]
const data = responses[1]
return new Response(renderTemplate(template, data), {
headers: {
'Content-Type': 'text/html'
}
})
})
)
})
äžç·
1ã€ã®ãã³ãã¬ãŒãã«å¶éããå¿ èŠã¯ãããŸãããã»ãšãã©ã®å ŽåãèŠæ±ã«å¿ããŠããããçµã¿åãããå¿ èŠããããŸããããšãã°ãèšç·Žãããã¹ãªã«ã¯ä»¥äžã䜿çšããŸãã
- æ°žç¶çãªUIèŠçŽ ã®ã¯ãŒã«ãŒã»ããã¢ãããã£ãã·ã³ã°
- Flickrã®ç»åãšããŒã¿ã«å¯ŸãããµãŒããŒã®å¿çã®ãã£ãã·ã³ã°
- ãã£ãã·ã¥ããããŒã¿ãååŸããã»ãšãã©ã®ãªã¯ãšã¹ãã§ãããã¯ãŒã¯ãã倱æããå Žå
- ããªãã¯æ€çŽ¢çµæã®ããã«ãã£ãã·ã¥ãããæ¬¡ã«WebãããªãœãŒã¹ãååŸãã
ãªã¯ãšã¹ããèŠãŠããããã©ãããããæ±ºããã ãã§ãã
self.addEventListener('fetch', event => {
// URL
const requestURL = new URL(event.request.url)
//
if (requestURL.hostname === 'api.example.com') {
event.respondWith(/* */)
return
}
//
if (requestURL.origin === location.origin) {
//
if (/^\/article\//.test(requestURL.pathname)) {
event.respondWith(/* */)
return
}
if (/\.webp$/.test(requestURL.pathname)) {
event.respondWith(/* */)
return
}
if (request.method == 'POST') {
event.respondWith(/* */)
return
}
if (/cheese/.test(requestURL.pathname)) {
event.respondWith(
// . .: - ?
new Response('Flagrant cheese error', {
//
status: 512
})
)
return
}
}
//
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
)
})
ãã®èšäºãã圹ã«ç«ãŠã°å¹žãã§ããæž èŽããããšãããããŸããã