Skip to content

Commit 7c826a1

Browse files
vtenfysDSchau
authored andcommitted
fix(gatsby-plugin-offline): fix certain resources being cached excessively (#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.
1 parent e9f2a6f commit 7c826a1

File tree

4 files changed

+42
-49
lines changed

4 files changed

+42
-49
lines changed

packages/gatsby-plugin-offline/README.md

+14-7
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,25 @@ const options = {
4949
navigateFallbackWhitelist: [/^([^.?]*|[^?]*\.([^.?]{5,}|html))(\?.*)?$/],
5050
navigateFallbackBlacklist: [/\?(.+&)?no-cache=1$/],
5151
cacheId: `gatsby-plugin-offline`,
52-
// Don't cache-bust JS or CSS files, and anything in the static directory
53-
dontCacheBustUrlsMatching: /(.*\.js$|.*\.css$|\/static\/)/,
52+
// Don't cache-bust JS or CSS files, and anything in the static directory,
53+
// since these files have unique URLs and their contents will never change
54+
dontCacheBustUrlsMatching: /(\.js$|\.css$|\/static\/)/,
5455
runtimeCaching: [
5556
{
56-
// Add runtime caching of various page resources.
57-
urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
57+
// Use cacheFirst since these don't need to be revalidated (same RegExp
58+
// and same reason as above)
59+
urlPattern: /(\.js$|\.css$|\/static\/)/,
60+
handler: `cacheFirst`,
61+
},
62+
{
63+
// Add runtime caching of various other page resources
64+
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
5865
handler: `staleWhileRevalidate`,
5966
},
6067
{
61-
// Use the Network First handler for external resources
62-
urlPattern: /^https?:/,
63-
handler: `networkFirst`,
68+
// Google Fonts CSS (doesn't end in .css so we need to specify it)
69+
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
70+
handler: `staleWhileRevalidate`,
6471
},
6572
],
6673
skipWaiting: true,

packages/gatsby-plugin-offline/src/gatsby-browser.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ exports.onServiceWorkerActive = ({
2121
// grab nodes from head of document
2222
const nodes = document.querySelectorAll(`
2323
head > script[src],
24-
head > link[as=script],
25-
head > link[rel=stylesheet],
24+
head > link[href],
2625
head > style[data-href]
2726
`)
2827

2928
// get all resource URLs
30-
const resources = [].slice
29+
const headerResources = [].slice
3130
.call(nodes)
3231
.map(node => node.src || node.href || node.getAttribute(`data-href`))
3332

@@ -40,8 +39,16 @@ exports.onServiceWorkerActive = ({
4039
)
4140
)
4241

43-
serviceWorker.active.postMessage({
44-
api: `gatsby-runtime-cache`,
45-
resources: [...resources, ...prefetchedResources],
42+
const resources = [...headerResources, ...prefetchedResources]
43+
resources.forEach(resource => {
44+
// Create a prefetch link for each resource, so Workbox runtime-caches them
45+
const link = document.createElement(`link`)
46+
link.rel = `prefetch`
47+
link.href = resource
48+
49+
link.onload = link.remove
50+
link.onerror = link.remove
51+
52+
document.head.appendChild(link)
4653
})
4754
}

packages/gatsby-plugin-offline/src/gatsby-node.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,25 @@ exports.onPostBuild = (args, pluginOptions) => {
9191
navigateFallbackWhitelist: [/^([^.?]*|[^?]*\.([^.?]{5,}|html))(\?.*)?$/],
9292
navigateFallbackBlacklist: [/\?(.+&)?no-cache=1$/],
9393
cacheId: `gatsby-plugin-offline`,
94-
// Don't cache-bust JS or CSS files, and anything in the static directory
95-
dontCacheBustUrlsMatching: /(.*\.js$|.*\.css$|\/static\/)/,
94+
// Don't cache-bust JS or CSS files, and anything in the static directory,
95+
// since these files have unique URLs and their contents will never change
96+
dontCacheBustUrlsMatching: /(\.js$|\.css$|\/static\/)/,
9697
runtimeCaching: [
9798
{
98-
// Add runtime caching of various page resources.
99-
urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
99+
// Use cacheFirst since these don't need to be revalidated (same RegExp
100+
// and same reason as above)
101+
urlPattern: /(\.js$|\.css$|\/static\/)/,
102+
handler: `cacheFirst`,
103+
},
104+
{
105+
// Add runtime caching of various other page resources
106+
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
100107
handler: `staleWhileRevalidate`,
101108
},
102109
{
103-
// Use the Network First handler for external resources
104-
urlPattern: /^https?:/,
105-
handler: `networkFirst`,
110+
// Google Fonts CSS (doesn't end in .css so we need to specify it)
111+
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
112+
handler: `staleWhileRevalidate`,
106113
},
107114
],
108115
skipWaiting: true,
Original file line numberDiff line numberDiff line change
@@ -1,29 +1 @@
1-
/* global workbox */
2-
3-
self.addEventListener(`message`, event => {
4-
const { api } = event.data
5-
if (api === `gatsby-runtime-cache`) {
6-
const { resources } = event.data
7-
const cacheName = workbox.core.cacheNames.runtime
8-
9-
event.waitUntil(
10-
caches.open(cacheName).then(cache =>
11-
Promise.all(
12-
resources.map(resource => {
13-
let request
14-
15-
// Some external resources don't allow
16-
// CORS so get an opaque response
17-
if (resource.match(/^https?:/)) {
18-
request = fetch(resource, { mode: `no-cors` })
19-
} else {
20-
request = fetch(resource)
21-
}
22-
23-
return request.then(response => cache.put(resource, response))
24-
})
25-
)
26-
)
27-
)
28-
}
29-
})
1+
// noop

0 commit comments

Comments
 (0)