Skip to content

Commit

Permalink
fix(gatsby-plugin-offline): fix certain resources being cached excess…
Browse files Browse the repository at this point in the history
…ively (#9923)

Fixes #9415

This PR leverages Workbox's automatic caching when a resource is fetched, by creating a `<link>` prefetch element for each resource. This means we don't have to worry about whether the resource can be fetched with CORS or not, since the browser handles it automatically. I've also changed the runtime caching RegExps so that only paths with certain extensions are cached, but 3rd party resources with these extensions can now be cached.
  • Loading branch information
valin4tor authored and DSchau committed Nov 14, 2018
1 parent e9f2a6f commit 7c826a1
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 49 deletions.
21 changes: 14 additions & 7 deletions packages/gatsby-plugin-offline/README.md
Expand Up @@ -49,18 +49,25 @@ const options = {
navigateFallbackWhitelist: [/^([^.?]*|[^?]*\.([^.?]{5,}|html))(\?.*)?$/],
navigateFallbackBlacklist: [/\?(.+&)?no-cache=1$/],
cacheId: `gatsby-plugin-offline`,
// Don't cache-bust JS or CSS files, and anything in the static directory
dontCacheBustUrlsMatching: /(.*\.js$|.*\.css$|\/static\/)/,
// Don't cache-bust JS or CSS files, and anything in the static directory,
// since these files have unique URLs and their contents will never change
dontCacheBustUrlsMatching: /(\.js$|\.css$|\/static\/)/,
runtimeCaching: [
{
// Add runtime caching of various page resources.
urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
// Use cacheFirst since these don't need to be revalidated (same RegExp
// and same reason as above)
urlPattern: /(\.js$|\.css$|\/static\/)/,
handler: `cacheFirst`,
},
{
// Add runtime caching of various other page resources
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: `staleWhileRevalidate`,
},
{
// Use the Network First handler for external resources
urlPattern: /^https?:/,
handler: `networkFirst`,
// Google Fonts CSS (doesn't end in .css so we need to specify it)
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: `staleWhileRevalidate`,
},
],
skipWaiting: true,
Expand Down
19 changes: 13 additions & 6 deletions packages/gatsby-plugin-offline/src/gatsby-browser.js
Expand Up @@ -21,13 +21,12 @@ exports.onServiceWorkerActive = ({
// grab nodes from head of document
const nodes = document.querySelectorAll(`
head > script[src],
head > link[as=script],
head > link[rel=stylesheet],
head > link[href],
head > style[data-href]
`)

// get all resource URLs
const resources = [].slice
const headerResources = [].slice
.call(nodes)
.map(node => node.src || node.href || node.getAttribute(`data-href`))

Expand All @@ -40,8 +39,16 @@ exports.onServiceWorkerActive = ({
)
)

serviceWorker.active.postMessage({
api: `gatsby-runtime-cache`,
resources: [...resources, ...prefetchedResources],
const resources = [...headerResources, ...prefetchedResources]
resources.forEach(resource => {
// Create a prefetch link for each resource, so Workbox runtime-caches them
const link = document.createElement(`link`)
link.rel = `prefetch`
link.href = resource

link.onload = link.remove
link.onerror = link.remove

document.head.appendChild(link)
})
}
21 changes: 14 additions & 7 deletions packages/gatsby-plugin-offline/src/gatsby-node.js
Expand Up @@ -91,18 +91,25 @@ exports.onPostBuild = (args, pluginOptions) => {
navigateFallbackWhitelist: [/^([^.?]*|[^?]*\.([^.?]{5,}|html))(\?.*)?$/],
navigateFallbackBlacklist: [/\?(.+&)?no-cache=1$/],
cacheId: `gatsby-plugin-offline`,
// Don't cache-bust JS or CSS files, and anything in the static directory
dontCacheBustUrlsMatching: /(.*\.js$|.*\.css$|\/static\/)/,
// Don't cache-bust JS or CSS files, and anything in the static directory,
// since these files have unique URLs and their contents will never change
dontCacheBustUrlsMatching: /(\.js$|\.css$|\/static\/)/,
runtimeCaching: [
{
// Add runtime caching of various page resources.
urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
// Use cacheFirst since these don't need to be revalidated (same RegExp
// and same reason as above)
urlPattern: /(\.js$|\.css$|\/static\/)/,
handler: `cacheFirst`,
},
{
// Add runtime caching of various other page resources
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: `staleWhileRevalidate`,
},
{
// Use the Network First handler for external resources
urlPattern: /^https?:/,
handler: `networkFirst`,
// Google Fonts CSS (doesn't end in .css so we need to specify it)
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: `staleWhileRevalidate`,
},
],
skipWaiting: true,
Expand Down
30 changes: 1 addition & 29 deletions packages/gatsby-plugin-offline/src/sw-append.js
@@ -1,29 +1 @@
/* global workbox */

self.addEventListener(`message`, event => {
const { api } = event.data
if (api === `gatsby-runtime-cache`) {
const { resources } = event.data
const cacheName = workbox.core.cacheNames.runtime

event.waitUntil(
caches.open(cacheName).then(cache =>
Promise.all(
resources.map(resource => {
let request

// Some external resources don't allow
// CORS so get an opaque response
if (resource.match(/^https?:/)) {
request = fetch(resource, { mode: `no-cors` })
} else {
request = fetch(resource)
}

return request.then(response => cache.put(resource, response))
})
)
)
)
}
})
// noop

0 comments on commit 7c826a1

Please sign in to comment.