Skip to content

Commit 2605aa0

Browse files
vtenfyspieh
authored andcommitted
fix(gatsby-plugin-offline): delay adding resources for paths until we have urls (#8613)
* Fix fetching resources before prefetch finishes * Pass onPostPrefetchPathname into onPrefetchPathname so plugins can call this when ready * Improve docs * Move onPostPrefetchPathname to the end * Refactor Guess.js plugin to use getResourcesForPathname Also make it easier to read by removing some unnecessary lines and changing indentation * Remove unnecessary lines * Undo accidental change * Call onPostPrefetchPathname from getResourcesForPathname * Refactor prefetching APIs * Remove comment + minor refactor * Remove unnecessary params * Refactor for consistency * Move API call outside the if-block * set api runner for loader earlier
1 parent 2ba57ea commit 2605aa0

File tree

7 files changed

+52
-74
lines changed

7 files changed

+52
-74
lines changed

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

+14-61
Original file line numberDiff line numberDiff line change
@@ -12,65 +12,18 @@ exports.onRouteUpdate = ({ location }) => {
1212
initialPath = location.pathname
1313
}
1414

15-
let chunksPromise
16-
const chunks = () => {
17-
if (!chunksPromise) {
18-
chunksPromise = fetch(`${window.location.origin}/webpack.stats.json`).then(
19-
res => res.json()
20-
)
21-
}
22-
23-
return chunksPromise
24-
}
25-
26-
let hasPrefetched = {}
27-
const prefetch = url => {
28-
if (hasPrefetched[url]) {
29-
return
30-
}
31-
hasPrefetched[url] = true
32-
const link = document.createElement(`link`)
33-
link.setAttribute(`rel`, `prefetch`)
34-
link.setAttribute(`href`, url)
35-
const parentElement =
36-
document.getElementsByTagName(`head`)[0] ||
37-
document.getElementsByName(`script`)[0].parentNode
38-
parentElement.appendChild(link)
39-
}
40-
41-
exports.onPrefetchPathname = ({ pathPrefix }, pluginOptions) => {
42-
if (process.env.NODE_ENV === `production`) {
43-
const matchedPaths = Object.keys(
44-
guess({
45-
path: window.location.pathname,
46-
threshold: pluginOptions.minimumThreshold,
47-
})
48-
)
49-
50-
// Don't prefetch from client for the initial path as we did that
51-
// during SSR
52-
if (notNavigated && initialPath === window.location.pathname) {
53-
return
54-
}
55-
56-
if (matchedPaths.length > 0) {
57-
matchedPaths.forEach(p => {
58-
chunks(p).then(chunk => {
59-
// eslint-disable-next-line
60-
const page = ___loader.getPage(p)
61-
if (!page) return
62-
let resources = []
63-
if (chunk.assetsByChunkName[page.componentChunkName]) {
64-
resources = resources.concat(
65-
chunk.assetsByChunkName[page.componentChunkName]
66-
)
67-
}
68-
// eslint-disable-next-line
69-
resources.push(`static/d/${___dataPaths[page.jsonName]}.json`)
70-
// TODO add support for pathPrefix
71-
resources.forEach(r => prefetch(`/${r}`))
72-
})
73-
})
74-
}
75-
}
15+
exports.onPrefetchPathname = ({ getResourcesForPathname }, pluginOptions) => {
16+
if (process.env.NODE_ENV !== `production`) return
17+
18+
const matchedPaths = Object.keys(
19+
guess({
20+
path: window.location.pathname,
21+
threshold: pluginOptions.minimumThreshold,
22+
})
23+
)
24+
25+
// Don't prefetch from client for the initial path as we did that
26+
// during SSR
27+
if (!(notNavigated && initialPath === window.location.pathname))
28+
matchedPaths.forEach(getResourcesForPathname)
7629
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ exports.registerServiceWorker = () => true
33
let swNotInstalled = true
44
const prefetchedPathnames = []
55

6-
exports.onPrefetchPathname = ({ pathname }) => {
6+
exports.onPostPrefetchPathname = ({ pathname }) => {
77
// if SW is not installed, we need to record any prefetches
88
// that happen so we can then add them to SW cache once installed
99
if (swNotInstalled && `serviceWorker` in navigator) {

packages/gatsby/cache-dir/app.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import { hot } from "react-hot-loader"
66
import socketIo from "./socketIo"
77
import emitter from "./emitter"
88
import { apiRunner, apiRunnerAsync } from "./api-runner-browser"
9-
import loader from "./loader"
9+
import loader, { setApiRunnerForLoader } from "./loader"
1010
import syncRequires from "./sync-requires"
1111
import pages from "./pages.json"
1212

1313
window.___emitter = emitter
14+
setApiRunnerForLoader(apiRunner)
1415

1516
// Let the site/plugins run code very early.
1617
apiRunnerAsync(`onClientEntry`).then(() => {

packages/gatsby/cache-dir/loader.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import prefetchHelper from "./prefetch"
55

66
const preferDefault = m => (m && m.default) || m
77

8-
let prefetcher
98
let devGetPageData
109
let inInitialRender = true
1110
let hasFetched = Object.create(null)
@@ -147,6 +146,20 @@ const handleResourceLoadError = (path, message) => {
147146
}
148147
}
149148

149+
const onPrefetchPathname = pathname => {
150+
if (!prefetchTriggered[pathname]) {
151+
apiRunner(`onPrefetchPathname`, { pathname: pathname })
152+
prefetchTriggered[pathname] = true
153+
}
154+
}
155+
156+
const onPostPrefetchPathname = pathname => {
157+
if (!prefetchCompleted[pathname]) {
158+
apiRunner(`onPostPrefetchPathname`, { pathname: pathname })
159+
prefetchCompleted[pathname] = true
160+
}
161+
}
162+
150163
// Note we're not actively using the path data atm. There
151164
// could be future optimizations however around trying to ensure
152165
// we load all resources for likely-to-be-visited paths.
@@ -163,6 +176,7 @@ const sortResourcesByCount = (a, b) => {
163176
let findPage
164177
let pathScriptsCache = {}
165178
let prefetchTriggered = {}
179+
let prefetchCompleted = {}
166180
let disableCorePrefetching = false
167181

168182
const queue = {
@@ -192,12 +206,7 @@ const queue = {
192206

193207
// Tell plugins with custom prefetching logic that they should start
194208
// prefetching this path.
195-
if (!prefetchTriggered[path]) {
196-
apiRunner(`onPrefetchPathname`, {
197-
pathname: path,
198-
})
199-
prefetchTriggered[path] = true
200-
}
209+
onPrefetchPathname(path)
201210

202211
// If a plugin has disabled core prefetching, stop now.
203212
if (disableCorePrefetching.some(a => a)) {
@@ -236,6 +245,9 @@ const queue = {
236245
prefetchResource(page.componentChunkName)
237246
}
238247

248+
// Tell plugins the path has been successfully prefetched
249+
onPostPrefetchPathname(path)
250+
239251
return true
240252
},
241253

@@ -375,6 +387,9 @@ const queue = {
375387
}
376388
})
377389
}
390+
391+
// Tell plugins the path has been successfully prefetched
392+
onPostPrefetchPathname(path)
378393
}),
379394
}
380395

packages/gatsby/cache-dir/navigation.js

-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ function init() {
127127
// Temp hack while awaiting https://github.com/reach/router/issues/119
128128
window.__navigatingToLink = false
129129

130-
setApiRunnerForLoader(apiRunner)
131130
window.___loader = loader
132131
window.___push = to => navigate(to, { replace: false })
133132
window.___replace = to => navigate(to, { replace: true })

packages/gatsby/cache-dir/production-app.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import emitter from "./emitter"
1414
window.___emitter = emitter
1515
import PageRenderer from "./page-renderer"
1616
import asyncRequires from "./async-requires"
17-
import loader from "./loader"
17+
import loader, { setApiRunnerForLoader } from "./loader"
1818
import loadDirectlyOr404 from "./load-directly-or-404"
1919
import EnsureResources from "./ensure-resources"
2020

@@ -25,6 +25,7 @@ window.___loader = loader
2525
loader.addPagesArray([window.page])
2626
loader.addDataPaths({ [window.page.jsonName]: window.dataPath })
2727
loader.addProdRequires(asyncRequires)
28+
setApiRunnerForLoader(apiRunner)
2829

2930
navigationInit()
3031

packages/gatsby/src/utils/api-browser-docs.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,20 @@ exports.wrapRootElement = true
159159
* Called when prefetching for a pathname is triggered. Allows
160160
* for plugins with custom prefetching logic.
161161
* @param {object} $0
162-
* @param {object} $0.pathname The pathname whose resources should now be prefetched
163-
* @param {object} $0.getResourcesForPathname Function for fetching resources related to pathname
162+
* @param {string} $0.pathname The pathname whose resources should now be prefetched
163+
* @param {function} $0.getResourcesForPathname Function for fetching resources related to pathname
164164
*/
165165
exports.onPrefetchPathname = true
166166

167+
/**
168+
* Called when prefetching for a pathname is successful. Allows
169+
* for plugins with custom prefetching logic.
170+
* @param {object} $0
171+
* @param {string} $0.pathname The pathname whose resources have now been prefetched
172+
* @param {function} $0.getResourceURLsForPathname Function for fetching URLs for resources related to the pathname
173+
*/
174+
exports.onPostPrefetchPathname = true
175+
167176
/**
168177
* Plugins can take over prefetching logic. If they do, they should call this
169178
* to disable the now duplicate core prefetching logic.

0 commit comments

Comments
 (0)