forked from cybrespace/pinafore
perf: download and cache polyfills on-the-fly (#814)
* perf: download and cache polyfills on-the-fly * fixup the localhost switch for service worker, does nothing
This commit is contained in:
parent
dbd6c35a88
commit
260f6acf0e
|
@ -143,6 +143,7 @@
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"dist",
|
"dist",
|
||||||
"src/routes/_utils/asyncModules.js",
|
"src/routes/_utils/asyncModules.js",
|
||||||
|
"src/routes/_utils/asyncPolyfills.js",
|
||||||
"src/routes/_components/dialog/asyncDialogs.js"
|
"src/routes/_components/dialog/asyncDialogs.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,26 +4,6 @@ export const importTimeline = () => import(
|
||||||
/* webpackChunkName: 'Timeline' */ '../_components/timeline/Timeline.html'
|
/* webpackChunkName: 'Timeline' */ '../_components/timeline/Timeline.html'
|
||||||
).then(getDefault)
|
).then(getDefault)
|
||||||
|
|
||||||
export const importIntersectionObserver = () => import(
|
|
||||||
/* webpackChunkName: 'intersection-observer' */ 'intersection-observer'
|
|
||||||
)
|
|
||||||
|
|
||||||
export const importRequestIdleCallback = () => import(
|
|
||||||
/* webpackChunkName: 'requestidlecallback' */ 'requestidlecallback'
|
|
||||||
)
|
|
||||||
|
|
||||||
export const importWebAnimationPolyfill = () => import(
|
|
||||||
/* webpackChunkName: 'web-animations-js' */ 'web-animations-js'
|
|
||||||
)
|
|
||||||
|
|
||||||
export const importIndexedDBGetAllShim = () => import(
|
|
||||||
/* webpackChunkName: 'indexeddb-getall-shim' */ 'indexeddb-getall-shim'
|
|
||||||
)
|
|
||||||
|
|
||||||
export const importCustomElementsPolyfill = () => import(
|
|
||||||
/* webpackChunkName: '@webcomponents/custom-elements' */ '@webcomponents/custom-elements'
|
|
||||||
)
|
|
||||||
|
|
||||||
export const importPageLifecycle = () => import(
|
export const importPageLifecycle = () => import(
|
||||||
/* webpackChunkName: 'page-lifecycle' */ 'page-lifecycle/dist/lifecycle.mjs'
|
/* webpackChunkName: 'page-lifecycle' */ 'page-lifecycle/dist/lifecycle.mjs'
|
||||||
).then(getDefault)
|
).then(getDefault)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
export const importIntersectionObserver = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-intersection-observer' */ 'intersection-observer'
|
||||||
|
)
|
||||||
|
|
||||||
|
export const importRequestIdleCallback = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-requestidlecallback' */ 'requestidlecallback'
|
||||||
|
)
|
||||||
|
|
||||||
|
export const importWebAnimationPolyfill = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-web-animations-js' */ 'web-animations-js'
|
||||||
|
)
|
||||||
|
|
||||||
|
export const importIndexedDBGetAllShim = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-indexeddb-getall-shim' */ 'indexeddb-getall-shim'
|
||||||
|
)
|
||||||
|
|
||||||
|
export const importCustomElementsPolyfill = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-@webcomponents/custom-elements' */ '@webcomponents/custom-elements'
|
||||||
|
)
|
|
@ -4,7 +4,7 @@ import {
|
||||||
importIntersectionObserver,
|
importIntersectionObserver,
|
||||||
importRequestIdleCallback,
|
importRequestIdleCallback,
|
||||||
importWebAnimationPolyfill
|
importWebAnimationPolyfill
|
||||||
} from './asyncModules'
|
} from './asyncPolyfills'
|
||||||
|
|
||||||
export function loadPolyfills () {
|
export function loadPolyfills () {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
|
|
|
@ -10,7 +10,7 @@ function onUpdateFound (registration) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!location.origin.match('localhost') && 'serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('/service-worker.js').then(registration => {
|
navigator.serviceWorker.register('/service-worker.js').then(registration => {
|
||||||
registration.addEventListener('updatefound', () => onUpdateFound(registration))
|
registration.addEventListener('updatefound', () => onUpdateFound(registration))
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,6 +4,11 @@ import {
|
||||||
routes as __routes__
|
routes as __routes__
|
||||||
} from '../__sapper__/service-worker.js'
|
} from '../__sapper__/service-worker.js'
|
||||||
|
|
||||||
|
import {
|
||||||
|
get,
|
||||||
|
post
|
||||||
|
} from './routes/_utils/ajax'
|
||||||
|
|
||||||
const timestamp = process.env.SAPPER_TIMESTAMP
|
const timestamp = process.env.SAPPER_TIMESTAMP
|
||||||
const ASSETS = `assets_${timestamp}`
|
const ASSETS = `assets_${timestamp}`
|
||||||
const WEBPACK_ASSETS = `webpack_assets_${timestamp}`
|
const WEBPACK_ASSETS = `webpack_assets_${timestamp}`
|
||||||
|
@ -17,7 +22,8 @@ const assets = __assets__
|
||||||
// `shell` is an array of all the files generated by webpack
|
// `shell` is an array of all the files generated by webpack
|
||||||
// also contains '/index.html' for some reason
|
// also contains '/index.html' for some reason
|
||||||
const webpackAssets = __shell__
|
const webpackAssets = __shell__
|
||||||
.filter(filename => !filename.endsWith('.map'))
|
.filter(filename => !filename.endsWith('.map')) // don't bother with sourcemaps
|
||||||
|
.filter(filename => !filename.includes('$polyfill$')) // polyfills are cached on-demand
|
||||||
|
|
||||||
// `routes` is an array of `{ pattern: RegExp }` objects that
|
// `routes` is an array of `{ pattern: RegExp }` objects that
|
||||||
// match the pages in your src
|
// match the pages in your src
|
||||||
|
@ -93,6 +99,13 @@ self.addEventListener('fetch', event => {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// for polyfills, cache them on-the-fly
|
||||||
|
if (url.pathname.includes('$polyfill$')) {
|
||||||
|
let response = await fetch(req)
|
||||||
|
// cache asynchronously, don't wait
|
||||||
|
caches.open(WEBPACK_ASSETS).then(cache => cache.put(req, response))
|
||||||
|
return response.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for everything else, go network-only
|
// for everything else, go network-only
|
||||||
|
@ -247,62 +260,3 @@ self.addEventListener('notificationclick', event => {
|
||||||
}
|
}
|
||||||
})())
|
})())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Copy-paste from ajax.js
|
|
||||||
async function get (url, headers, options) {
|
|
||||||
return _fetch(url, makeFetchOptions('GET', headers), options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function post (url, body, headers, options) {
|
|
||||||
return _putOrPostOrPatch('POST', url, body, headers, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _putOrPostOrPatch (method, url, body, headers, options) {
|
|
||||||
let fetchOptions = makeFetchOptions(method, headers)
|
|
||||||
if (body) {
|
|
||||||
if (body instanceof FormData) {
|
|
||||||
fetchOptions.body = body
|
|
||||||
} else {
|
|
||||||
fetchOptions.body = JSON.stringify(body)
|
|
||||||
fetchOptions.headers['Content-Type'] = 'application/json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _fetch(url, fetchOptions, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function _fetch (url, fetchOptions, options) {
|
|
||||||
let response
|
|
||||||
if (options && options.timeout) {
|
|
||||||
response = await fetchWithTimeout(url, fetchOptions, options.timeout)
|
|
||||||
} else {
|
|
||||||
response = await fetch(url, fetchOptions)
|
|
||||||
}
|
|
||||||
return throwErrorIfInvalidResponse(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function throwErrorIfInvalidResponse (response) {
|
|
||||||
let json = await response.json()
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
if (json && json.error) {
|
|
||||||
throw new Error(response.status + ': ' + json.error)
|
|
||||||
}
|
|
||||||
throw new Error('Request failed: ' + response.status)
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchWithTimeout (url, fetchOptions, timeout) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fetch(url, fetchOptions).then(resolve, reject)
|
|
||||||
setTimeout(() => reject(new Error(`Timed out after ${timeout / 1000} seconds`)), timeout)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeFetchOptions (method, headers) {
|
|
||||||
return {
|
|
||||||
method,
|
|
||||||
headers: Object.assign(headers || {}, {
|
|
||||||
'Accept': 'application/json'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue