Skip to content

Commit ae6eab3

Browse files
vtenfysGatsbyJS Bot
authored and
GatsbyJS Bot
committed
fix(gatsby-plugin-offline): Improve reliability of JS detection (#18760)
* Combine offline API with redirection to improve reliability over preload * fix API route not working for navigation requests + make code order more logical * check if API method exists before calling function * add comments to relevant sections
1 parent 4d5d780 commit ae6eab3

File tree

2 files changed

+70
-37
lines changed

2 files changed

+70
-37
lines changed

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,10 @@ export const onRenderBody = ({ pathname, setHeadComponents }) => {
3030

3131
setHeadComponents([
3232
<noscript key="disable-offline-shell">
33-
<link
34-
rel="preload"
35-
as="fetch"
36-
href="/.gatsby-plugin-offline:disableOfflineShell"
33+
<meta
34+
httpEquiv="refresh"
35+
content="0;url=/.gatsby-plugin-offline:api=disableOfflineShell&redirect=true"
3736
/>
38-
<meta httpEquiv="refresh" content="0;url=" />
3937
</noscript>,
4038
])
4139
}

packages/gatsby-plugin-offline/src/sw-append.js

+67-32
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,78 @@
33
importScripts(`idb-keyval-iife.min.js`)
44

55
const { NavigationRoute } = workbox.routing
6+
7+
let lastNavigationRequest = null
68
let offlineShellEnabled = true
79

10+
// prefer standard object syntax to support more browsers
11+
const MessageAPI = {
12+
setPathResources: (event, { path, resources }) => {
13+
event.waitUntil(idbKeyval.set(`resources:${path}`, resources))
14+
},
15+
16+
clearPathResources: event => {
17+
event.waitUntil(idbKeyval.clear())
18+
},
19+
20+
enableOfflineShell: () => {
21+
offlineShellEnabled = true
22+
},
23+
24+
disableOfflineShell: () => {
25+
offlineShellEnabled = false
26+
},
27+
}
28+
29+
self.addEventListener(`message`, event => {
30+
const { gatsbyApi: api } = event.data
31+
if (api) MessageAPI[api](event, event.data)
32+
})
33+
34+
function handleAPIRequest({ event }) {
35+
const { pathname } = new URL(event.request.url)
36+
37+
const params = pathname.match(/:(.+)/)[1]
38+
const data = {}
39+
40+
if (params.indexOf(`=`) !== -1) {
41+
params.split(`&`).forEach(param => {
42+
const [key, val] = param.split(`=`)
43+
data[key] = val
44+
})
45+
} else {
46+
data.api = params
47+
}
48+
49+
if (MessageAPI[data.api] !== undefined) {
50+
MessageAPI[data.api]()
51+
}
52+
53+
if (!data.redirect) {
54+
return new Response()
55+
}
56+
57+
return new Response(null, {
58+
status: 302,
59+
headers: {
60+
Location: lastNavigationRequest,
61+
},
62+
})
63+
}
64+
865
const navigationRoute = new NavigationRoute(async ({ event }) => {
66+
// handle API requests separately to normal navigation requests, so do this
67+
// check first
68+
if (event.request.url.match(/\/.gatsby-plugin-offline:.+/)) {
69+
return handleAPIRequest({ event })
70+
}
71+
972
if (!offlineShellEnabled) {
1073
return await fetch(event.request)
1174
}
1275

76+
lastNavigationRequest = event.request.url
77+
1378
let { pathname } = new URL(event.request.url)
1479
pathname = pathname.replace(new RegExp(`^%pathPrefix%`), ``)
1580

@@ -36,35 +101,5 @@ const navigationRoute = new NavigationRoute(async ({ event }) => {
36101

37102
workbox.routing.registerRoute(navigationRoute)
38103

39-
// prefer standard object syntax to support more browsers
40-
const MessageAPI = {
41-
setPathResources: (event, { path, resources }) => {
42-
event.waitUntil(idbKeyval.set(`resources:${path}`, resources))
43-
},
44-
45-
clearPathResources: event => {
46-
event.waitUntil(idbKeyval.clear())
47-
},
48-
49-
enableOfflineShell: () => {
50-
offlineShellEnabled = true
51-
},
52-
53-
disableOfflineShell: () => {
54-
offlineShellEnabled = false
55-
},
56-
}
57-
58-
self.addEventListener(`message`, event => {
59-
const { gatsbyApi: api } = event.data
60-
if (api) MessageAPI[api](event, event.data)
61-
})
62-
63-
workbox.routing.registerRoute(/\/.gatsby-plugin-offline:.+/, ({ event }) => {
64-
const { pathname } = new URL(event.request.url)
65-
66-
const api = pathname.match(/:(.+)/)[1]
67-
MessageAPI[api]()
68-
69-
return new Response()
70-
})
104+
// this route is used when performing a non-navigation request (e.g. fetch)
105+
workbox.routing.registerRoute(/\/.gatsby-plugin-offline:.+/, handleAPIRequest)

0 commit comments

Comments
 (0)