more work on service worker
This commit is contained in:
parent
0b442bb2a6
commit
01243ba4c1
14
routes/_utils/asyncModules.js
Normal file
14
routes/_utils/asyncModules.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
const importURLSearchParams = () => import(
|
||||||
|
/* webpackChunkName: 'url-search-params' */ 'url-search-params'
|
||||||
|
).then(Params => {
|
||||||
|
window.URLSearchParams = Params
|
||||||
|
Object.defineProperty(window.URL.prototype, 'searchParams', {
|
||||||
|
get() {
|
||||||
|
return new Params(this.search)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
export {
|
||||||
|
importURLSearchParams
|
||||||
|
}
|
|
@ -1,16 +1,19 @@
|
||||||
import { init } from 'sapper/runtime.js';
|
import { init } from 'sapper/runtime.js'
|
||||||
|
import toast from '../routes/_utils/toast.js'
|
||||||
|
|
||||||
// polyfills
|
// polyfills
|
||||||
Promise.all([
|
Promise.all([
|
||||||
typeof URLSearchParams === 'undefined' && import(/* webpackChunkName: 'url-search-params' */ 'url-search-params').then(Params => {
|
typeof URLSearchParams === 'undefined' && importURLParams()
|
||||||
window.URLSearchParams = Params
|
|
||||||
Object.defineProperty(window.URL.prototype, 'searchParams', {
|
|
||||||
get() {
|
|
||||||
return new Params(this.search)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
// `routes` is an array of route objects injected by Sapper
|
// `routes` is an array of route objects injected by Sapper
|
||||||
init(document.querySelector('#sapper'), __routes__)
|
init(document.querySelector('#sapper'), __routes__)
|
||||||
|
|
||||||
|
if (navigator.serviceWorker && navigator.serviceWorker.controller) {
|
||||||
|
navigator.serviceWorker.controller.onstatechange = (e) => {
|
||||||
|
if (e.target.state === 'redundant') {
|
||||||
|
toast.say('App update available. Reload to update.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
|
@ -36,8 +36,18 @@ self.addEventListener('activate', event => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const NETWORK_ONLY = [
|
||||||
|
'/oauth'
|
||||||
|
]
|
||||||
|
|
||||||
|
const CACHE_FIRST = [
|
||||||
|
'/api/v1/accounts/verify_credentials',
|
||||||
|
'/system/accounts/avatars'
|
||||||
|
]
|
||||||
|
|
||||||
self.addEventListener('fetch', event => {
|
self.addEventListener('fetch', event => {
|
||||||
const url = new URL(event.request.url)
|
const req = event.request
|
||||||
|
const url = new URL(req.url)
|
||||||
|
|
||||||
// don't try to handle e.g. data: URIs
|
// don't try to handle e.g. data: URIs
|
||||||
if (!url.protocol.startsWith('http')) {
|
if (!url.protocol.startsWith('http')) {
|
||||||
|
@ -46,7 +56,7 @@ self.addEventListener('fetch', event => {
|
||||||
|
|
||||||
// always serve assets and webpack-generated files from cache
|
// always serve assets and webpack-generated files from cache
|
||||||
if (cached.has(url.pathname)) {
|
if (cached.has(url.pathname)) {
|
||||||
event.respondWith(caches.match(event.request))
|
event.respondWith(caches.match(req))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,24 +65,53 @@ self.addEventListener('fetch', event => {
|
||||||
// app, but if it's right for yours then uncomment this section
|
// app, but if it's right for yours then uncomment this section
|
||||||
|
|
||||||
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
|
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
|
||||||
event.respondWith(caches.match('/index.html'));
|
event.respondWith(caches.match('/index.html'))
|
||||||
return;
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-GET and for certain endpoints (e.g. OAuth), go network-only
|
||||||
|
if (req.method !== 'GET' ||
|
||||||
|
NETWORK_ONLY.some(pattern => url.pathname.startsWith(pattern))) {
|
||||||
|
console.log('Using network-only for', url.href)
|
||||||
|
event.respondWith(fetch(req))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// For these, go cache-first.
|
||||||
|
if (CACHE_FIRST.some(pattern => url.pathname.startsWith(pattern))) {
|
||||||
|
console.log('Using cache-first for', url.href)
|
||||||
|
event.respondWith(caches
|
||||||
|
.open(`offline${timestamp}`)
|
||||||
|
.then(async cache => {
|
||||||
|
let response = await cache.match(req)
|
||||||
|
if (response) {
|
||||||
|
// update asynchronously
|
||||||
|
fetch(req).then(response => {
|
||||||
|
cache.put(req, response.clone())
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
response = await fetch(req)
|
||||||
|
cache.put(req, response.clone())
|
||||||
|
return response
|
||||||
|
}))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// for everything else, try the network first, falling back to
|
// for everything else, try the network first, falling back to
|
||||||
// cache if the user is offline. (If the pages never change, you
|
// cache if the user is offline. (If the pages never change, you
|
||||||
// might prefer a cache-first approach to a network-first one.)
|
// might prefer a cache-first approach to a network-first one.)
|
||||||
event.respondWith(
|
event.respondWith(caches
|
||||||
caches
|
|
||||||
.open(`offline${timestamp}`)
|
.open(`offline${timestamp}`)
|
||||||
.then(async cache => {
|
.then(async cache => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(event.request)
|
console.log('Using network-first for', url.href)
|
||||||
cache.put(event.request, response.clone())
|
const response = await fetch(req)
|
||||||
|
cache.put(req, response.clone())
|
||||||
return response
|
return response
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const response = await cache.match(event.request)
|
const response = await cache.match(req)
|
||||||
if (response) {
|
if (response) {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue