diff --git a/packages/gatsby-plugin-offline/README.md b/packages/gatsby-plugin-offline/README.md
index 809cc3b41db64..d35ee7630cc4f 100644
--- a/packages/gatsby-plugin-offline/README.md
+++ b/packages/gatsby-plugin-offline/README.md
@@ -24,8 +24,8 @@ plugins: [`gatsby-plugin-offline`]
When adding this plugin to your `gatsby-config.js`, you can pass in options to
override the default [Workbox](https://developers.google.com/web/tools/workbox/modules/workbox-build) config.
-The default config is as follows. Warning, you can break the offline support
-and AppCache setup by changing these options so tread carefully.
+The default config is as follows. Warning: you can break the offline support by
+changing these options, so tread carefully.
```javascript
const options = {
@@ -37,17 +37,6 @@ const options = {
// the default prefix with `pathPrefix`.
"/": `${pathPrefix}/`,
},
- navigateFallback: `${pathPrefix}/offline-plugin-app-shell-fallback/index.html`,
- // Only match URLs without extensions or the query `no-cache=1`.
- // So example.com/about/ will pass but
- // example.com/about/?no-cache=1 and
- // example.com/cheeseburger.jpg will not.
- // We only want the service worker to handle our "clean"
- // URLs and not any files hosted on the site.
- //
- // Regex based on http://stackoverflow.com/a/18017805
- 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,
// since these files have unique URLs and their contents will never change
diff --git a/packages/gatsby-plugin-offline/package.json b/packages/gatsby-plugin-offline/package.json
index 6471db1d46af5..9e23bf885ea51 100644
--- a/packages/gatsby-plugin-offline/package.json
+++ b/packages/gatsby-plugin-offline/package.json
@@ -9,6 +9,7 @@
"dependencies": {
"@babel/runtime": "^7.0.0",
"cheerio": "^1.0.0-rc.2",
+ "idb-keyval": "^3.1.0",
"lodash": "^4.17.10",
"workbox-build": "^3.6.3"
},
diff --git a/packages/gatsby-plugin-offline/src/gatsby-browser.js b/packages/gatsby-plugin-offline/src/gatsby-browser.js
index 0f5749e483eb9..947a2bc2649e6 100644
--- a/packages/gatsby-plugin-offline/src/gatsby-browser.js
+++ b/packages/gatsby-plugin-offline/src/gatsby-browser.js
@@ -1,23 +1,12 @@
exports.registerServiceWorker = () => true
-let swNotInstalled = true
const prefetchedPathnames = []
-
-exports.onPostPrefetchPathname = ({ pathname }) => {
- // if SW is not installed, we need to record any prefetches
- // that happen so we can then add them to SW cache once installed
- if (swNotInstalled && `serviceWorker` in navigator) {
- prefetchedPathnames.push(pathname)
- }
-}
+const whitelistedPathnames = []
exports.onServiceWorkerActive = ({
getResourceURLsForPathname,
serviceWorker,
}) => {
- // stop recording prefetch events
- swNotInstalled = false
-
// grab nodes from head of document
const nodes = document.querySelectorAll(`
head > script[src],
@@ -51,4 +40,40 @@ exports.onServiceWorkerActive = ({
document.head.appendChild(link)
})
+
+ serviceWorker.active.postMessage({
+ gatsbyApi: `whitelistPathnames`,
+ pathnames: whitelistedPathnames,
+ })
+}
+
+function whitelistPathname(pathname, includesPrefix) {
+ if (`serviceWorker` in navigator) {
+ const { serviceWorker } = navigator
+
+ if (serviceWorker.controller !== null) {
+ serviceWorker.controller.postMessage({
+ gatsbyApi: `whitelistPathnames`,
+ pathnames: [{ pathname, includesPrefix }],
+ })
+ } else {
+ whitelistedPathnames.push({ pathname, includesPrefix })
+ }
+ }
+}
+
+exports.onPostPrefetchPathname = ({ pathname }) => {
+ whitelistPathname(pathname, false)
+
+ // if SW is not installed, we need to record any prefetches
+ // that happen so we can then add them to SW cache once installed
+ if (
+ `serviceWorker` in navigator &&
+ !(
+ navigator.serviceWorker.controller !== null &&
+ navigator.serviceWorker.controller.state === `activated`
+ )
+ ) {
+ prefetchedPathnames.push(pathname)
+ }
}
diff --git a/packages/gatsby-plugin-offline/src/gatsby-node.js b/packages/gatsby-plugin-offline/src/gatsby-node.js
index 892e99eb953dc..c522b426b51f1 100644
--- a/packages/gatsby-plugin-offline/src/gatsby-node.js
+++ b/packages/gatsby-plugin-offline/src/gatsby-node.js
@@ -79,17 +79,6 @@ exports.onPostBuild = (args, pluginOptions) => {
// the default prefix with `pathPrefix`.
"/": `${pathPrefix}/`,
},
- navigateFallback: `${pathPrefix}/offline-plugin-app-shell-fallback/index.html`,
- // Only match URLs without extensions or the query `no-cache=1`.
- // So example.com/about/ will pass but
- // example.com/about/?no-cache=1 and
- // example.com/cheeseburger.jpg will not.
- // We only want the service worker to handle our "clean"
- // URLs and not any files hosted on the site.
- //
- // Regex based on http://stackoverflow.com/a/18017805
- 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,
// since these files have unique URLs and their contents will never change
@@ -122,15 +111,22 @@ exports.onPostBuild = (args, pluginOptions) => {
delete pluginOptions.plugins
const combinedOptions = _.defaults(pluginOptions, options)
+ const idbKeyvalFile = `idb-keyval-iife.min.js`
+ const idbKeyvalSource = require.resolve(`idb-keyval/dist/${idbKeyvalFile}`)
+ const idbKeyvalDest = `public/${idbKeyvalFile}`
+ fs.createReadStream(idbKeyvalSource).pipe(fs.createWriteStream(idbKeyvalDest))
+
const swDest = `public/sw.js`
return workboxBuild
.generateSW({ swDest, ...combinedOptions })
.then(({ count, size, warnings }) => {
if (warnings) warnings.forEach(warning => console.warn(warning))
- const swAppend = fs.readFileSync(`${__dirname}/sw-append.js`)
- fs.appendFileSync(`public/sw.js`, swAppend)
+ const swAppend = fs
+ .readFileSync(`${__dirname}/sw-append.js`, `utf8`)
+ .replace(/%pathPrefix%/g, pathPrefix)
+ fs.appendFileSync(`public/sw.js`, swAppend)
console.log(
`Generated ${swDest}, which will precache ${count} files, totaling ${size} bytes.`
)
diff --git a/packages/gatsby-plugin-offline/src/sw-append.js b/packages/gatsby-plugin-offline/src/sw-append.js
index 172f1ae6a468c..0d6c4a191d467 100644
--- a/packages/gatsby-plugin-offline/src/sw-append.js
+++ b/packages/gatsby-plugin-offline/src/sw-append.js
@@ -1 +1,83 @@
-// noop
+/* global importScripts, workbox, idbKeyval */
+
+importScripts(`idb-keyval-iife.min.js`)
+const WHITELIST_KEY = `custom-navigation-whitelist`
+
+const navigationRoute = new workbox.routing.NavigationRoute(({ event }) => {
+ const { pathname } = new URL(event.request.url)
+
+ return idbKeyval.get(WHITELIST_KEY).then((customWhitelist = []) => {
+ // Respond with the offline shell if we match the custom whitelist
+ if (customWhitelist.includes(pathname)) {
+ const offlineShell = `%pathPrefix%/offline-plugin-app-shell-fallback/index.html`
+ const cacheName = workbox.core.cacheNames.precache
+
+ return caches.match(offlineShell, { cacheName })
+ }
+
+ return fetch(event.request)
+ })
+})
+
+workbox.routing.registerRoute(navigationRoute)
+
+let updatingWhitelist = null
+
+function rawWhitelistPathnames(pathnames) {
+ if (updatingWhitelist !== null) {
+ // Prevent the whitelist from being updated twice at the same time
+ return updatingWhitelist.then(() => rawWhitelistPathnames(pathnames))
+ }
+
+ updatingWhitelist = idbKeyval
+ .get(WHITELIST_KEY)
+ .then((customWhitelist = []) => {
+ pathnames.forEach(pathname => {
+ if (!customWhitelist.includes(pathname)) customWhitelist.push(pathname)
+ })
+
+ return idbKeyval.set(WHITELIST_KEY, customWhitelist)
+ })
+ .then(() => {
+ updatingWhitelist = null
+ })
+
+ return updatingWhitelist
+}
+
+function rawResetWhitelist() {
+ if (updatingWhitelist !== null) {
+ return updatingWhitelist.then(() => rawResetWhitelist())
+ }
+
+ updatingWhitelist = idbKeyval.set(WHITELIST_KEY, []).then(() => {
+ updatingWhitelist = null
+ })
+
+ return updatingWhitelist
+}
+
+const messageApi = {
+ whitelistPathnames(event) {
+ let { pathnames } = event.data
+
+ pathnames = pathnames.map(({ pathname, includesPrefix }) => {
+ if (!includesPrefix) {
+ return `%pathPrefix%${pathname}`
+ } else {
+ return pathname
+ }
+ })
+
+ event.waitUntil(rawWhitelistPathnames(pathnames))
+ },
+
+ resetWhitelist(event) {
+ event.waitUntil(rawResetWhitelist())
+ },
+}
+
+self.addEventListener(`message`, event => {
+ const { gatsbyApi } = event.data
+ if (gatsbyApi) messageApi[gatsbyApi](event)
+})
diff --git a/packages/gatsby/cache-dir/ensure-resources.js b/packages/gatsby/cache-dir/ensure-resources.js
index c94146cd181c0..c05a82673ae29 100644
--- a/packages/gatsby/cache-dir/ensure-resources.js
+++ b/packages/gatsby/cache-dir/ensure-resources.js
@@ -2,7 +2,6 @@ import React from "react"
import PropTypes from "prop-types"
import loader from "./loader"
import shallowCompare from "shallow-compare"
-import { getRedirectUrl } from "./load-directly-or-404"
// Pass pathname in as prop.
// component will try fetching resources. If they exist,
@@ -94,15 +93,19 @@ class EnsureResources extends React.Component {
}
render() {
+ // This should only occur if the network is offline, or if the
+ // path is nonexistent and there's no custom 404 page.
if (
process.env.NODE_ENV === `production` &&
!(this.state.pageResources && this.state.pageResources.json)
) {
- // This should only occur if there's no custom 404 page
- const url = getRedirectUrl(this.state.location.href)
- if (url) {
- window.location.replace(url)
- }
+ // Do this, rather than simply `window.location.reload()`, so that
+ // pressing the back/forward buttons work - otherwise Reach Router will
+ // try to handle back/forward navigation, causing the URL to change but
+ // the page displayed to stay the same.
+ const originalUrl = new URL(location.href)
+ window.history.replaceState({}, `404`, `${location.pathname}?gatsby-404`)
+ window.location.replace(originalUrl)
return null
}
diff --git a/packages/gatsby/cache-dir/load-directly-or-404.js b/packages/gatsby/cache-dir/load-directly-or-404.js
deleted file mode 100644
index f232c3f55c114..0000000000000
--- a/packages/gatsby/cache-dir/load-directly-or-404.js
+++ /dev/null
@@ -1,72 +0,0 @@
-export function getRedirectUrl(path) {
- const url = new URL(path, window.location.origin)
-
- // This should never happen, but check just in case - otherwise, there would
- // be an infinite redirect loop
- if (url.search.match(/\?(.*&)?no-cache=1(&|$)/)) {
- console.error(
- `Found no-cache=1 while attempting to load a page directly; ` +
- `this is likely due to a bug in Gatsby, or a misconfiguration in your project.`
- )
- return false
- }
-
- // Append the appropriate query to the URL.
- if (url.search) {
- url.search += `&no-cache=1`
- } else {
- url.search = `?no-cache=1`
- }
-
- return url
-}
-
-/**
- * When other parts of the code can't find resources for a page, they load the 404 page's
- * resources (if it exists) and then pass them here. This module then does the following:
- * 1. Checks if 404 pages resources exist. If not, just navigate directly to the desired URL
- * to show whatever server 404 page exists.
- * 2. Try fetching the desired page to see if it exists on the server but we
- * were just prevented from seeing it due to loading the site from a SW. If this is the case,
- * trigger a hard reload to grab that page from the server.
- * 3. If the page doesn't exist, show the normal 404 page component.
- * 4. If the fetch failed (generally meaning we're offline), then navigate anyways to show
- * either the browser's offline page or whatever the server error is.
- */
-export default function(resources, path, replaceOnSuccess = false) {
- return new Promise((resolve, reject) => {
- const url = getRedirectUrl(path)
- if (!url) {
- reject(url)
- return
- }
-
- // Always navigate directly if a custom 404 page doesn't exist.
- if (!resources) {
- window.location = url
- } else {
- // Now test if the page is available directly
- fetch(url.href)
- .then(response => {
- if (response.status !== 404) {
- // Redirect there if there isn't a 404. If a different HTTP
- // error occurs, the appropriate error message will be
- // displayed after loading the page directly.
- if (replaceOnSuccess) {
- window.location.replace(url)
- } else {
- window.location = url
- }
- } else {
- // If a 404 occurs, show the custom 404 page.
- resolve()
- }
- })
- .catch(() => {
- // If an error occurs (usually when offline), navigate to the
- // page anyway to show the browser's proper offline error page
- window.location = url
- })
- }
- })
-}
diff --git a/packages/gatsby/cache-dir/loader.js b/packages/gatsby/cache-dir/loader.js
index 392d12e285477..23a3dde924a7e 100644
--- a/packages/gatsby/cache-dir/loader.js
+++ b/packages/gatsby/cache-dir/loader.js
@@ -1,6 +1,5 @@
import pageFinderFactory from "./find-page"
import emitter from "./emitter"
-import stripPrefix from "./strip-prefix"
import prefetchHelper from "./prefetch"
const preferDefault = m => (m && m.default) || m
@@ -16,7 +15,6 @@ let fetchingPageResourceMapPromise = null
let fetchedPageResourceMap = false
let apiRunner
const failedPaths = {}
-const failedResources = {}
const MAX_HISTORY = 5
const jsonPromiseStore = {}
@@ -72,6 +70,7 @@ const fetchResource = resourceName => {
if (req.status === 200) {
resolve(JSON.parse(req.responseText))
} else {
+ delete jsonPromiseStore[resourceName]
reject()
}
}
@@ -90,7 +89,8 @@ const fetchResource = resourceName => {
const fetchPromise = resourceFunction()
let failed = false
return fetchPromise
- .catch(() => {
+ .catch(e => {
+ console.error(e)
failed = true
})
.then(component => {
@@ -99,10 +99,6 @@ const fetchResource = resourceName => {
succeeded: !failed,
})
- if (!failedResources[resourceName]) {
- failedResources[resourceName] = failed
- }
-
fetchHistory = fetchHistory.slice(-MAX_HISTORY)
resolve(component)
@@ -112,10 +108,12 @@ const fetchResource = resourceName => {
const prefetchResource = resourceName => {
if (resourceName.slice(0, 12) === `component---`) {
- createComponentUrls(resourceName).forEach(url => prefetchHelper(url))
+ return Promise.all(
+ createComponentUrls(resourceName).map(url => prefetchHelper(url))
+ )
} else {
const url = createJsonURL(jsonDataPaths[resourceName])
- prefetchHelper(url)
+ return prefetchHelper(url)
}
}
@@ -148,14 +146,14 @@ const handleResourceLoadError = (path, message) => {
const onPrefetchPathname = pathname => {
if (!prefetchTriggered[pathname]) {
- apiRunner(`onPrefetchPathname`, { pathname: pathname })
+ apiRunner(`onPrefetchPathname`, { pathname })
prefetchTriggered[pathname] = true
}
}
const onPostPrefetchPathname = pathname => {
if (!prefetchCompleted[pathname]) {
- apiRunner(`onPostPrefetchPathname`, { pathname: pathname })
+ apiRunner(`onPostPrefetchPathname`, { pathname })
prefetchCompleted[pathname] = true
}
}
@@ -188,12 +186,10 @@ const queue = {
// Hovering on a link is a very strong indication the user is going to
// click on it soon so let's start prefetching resources for this
// pathname.
- hovering: rawPath => {
- const path = stripPrefix(rawPath, __PATH_PREFIX__)
+ hovering: path => {
queue.getResourcesForPathname(path)
},
- enqueue: rawPath => {
- const path = stripPrefix(rawPath, __PATH_PREFIX__)
+ enqueue: path => {
if (!apiRunner)
console.error(`Run setApiRunnerForLoader() before enqueing paths`)
@@ -218,7 +214,7 @@ const queue = {
) {
// If page wasn't found check and we didn't fetch resources map for
// all pages, wait for fetch to complete and try find page again
- return fetchPageResourceMap().then(() => queue.enqueue(rawPath))
+ return fetchPageResourceMap().then(() => queue.enqueue(path))
}
if (!page) {
@@ -234,13 +230,15 @@ const queue = {
// Prefetch resources.
if (process.env.NODE_ENV === `production`) {
- prefetchResource(page.jsonName)
- prefetchResource(page.componentChunkName)
+ Promise.all([
+ prefetchResource(page.jsonName),
+ prefetchResource(page.componentChunkName),
+ ]).then(() => {
+ // Tell plugins the path has been successfully prefetched
+ onPostPrefetchPathname(path)
+ })
}
- // Tell plugins the path has been successfully prefetched
- onPostPrefetchPathname(path)
-
return true
},
@@ -350,6 +348,9 @@ const queue = {
page,
pageResources,
})
+ // Tell plugins the path has been successfully prefetched
+ onPostPrefetchPathname(path)
+
resolve(pageResources)
})
} else {
@@ -378,6 +379,9 @@ const queue = {
pageResources,
})
+ // Tell plugins the path has been successfully prefetched
+ onPostPrefetchPathname(path)
+
if (doingInitialRender) {
// We got all resources needed for first mount,
// we can fetch resoures for all pages.
@@ -385,9 +389,6 @@ const queue = {
}
})
}
-
- // Tell plugins the path has been successfully prefetched
- onPostPrefetchPathname(path)
}),
}
diff --git a/packages/gatsby/cache-dir/navigation.js b/packages/gatsby/cache-dir/navigation.js
index 3eb6728c45298..1932dfc64d491 100644
--- a/packages/gatsby/cache-dir/navigation.js
+++ b/packages/gatsby/cache-dir/navigation.js
@@ -6,7 +6,6 @@ import { apiRunner } from "./api-runner-browser"
import emitter from "./emitter"
import { navigate as reachNavigate } from "@reach/router"
import parsePath from "./parse-path"
-import loadDirectlyOr404 from "./load-directly-or-404"
// Convert to a map for faster lookup in maybeRedirect()
const redirectMap = redirects.reduce((map, redirect) => {
@@ -66,8 +65,12 @@ const navigate = (to, options = {}) => {
pathname = parsePath(to).pathname
}
- // If we had a service worker update, no matter the path, reload window
+ // If we had a service worker update, no matter the path, reload window and
+ // reset the pathname whitelist
if (window.GATSBY_SW_UPDATED) {
+ const { controller } = navigator.serviceWorker
+ controller.postMessage({ gatsbyApi: `resetWhitelist` })
+
window.location = pathname
return
}
@@ -82,18 +85,8 @@ const navigate = (to, options = {}) => {
}, 1000)
loader.getResourcesForPathname(pathname).then(pageResources => {
- if (
- (!pageResources || pageResources.page.path === `/404.html`) &&
- process.env.NODE_ENV === `production`
- ) {
- clearTimeout(timeoutId)
- loadDirectlyOr404(pageResources, to).then(() =>
- reachNavigate(to, options)
- )
- } else {
- reachNavigate(to, options)
- clearTimeout(timeoutId)
- }
+ reachNavigate(to, options)
+ clearTimeout(timeoutId)
})
}
diff --git a/packages/gatsby/cache-dir/prefetch.js b/packages/gatsby/cache-dir/prefetch.js
index 82c119ccb5a43..1d6322d8aeeca 100644
--- a/packages/gatsby/cache-dir/prefetch.js
+++ b/packages/gatsby/cache-dir/prefetch.js
@@ -12,23 +12,44 @@ const support = function(feature) {
}
return false
}
+
const linkPrefetchStrategy = function(url) {
- if (typeof document === `undefined`) {
- return
- }
- const link = document.createElement(`link`)
- link.setAttribute(`rel`, `prefetch`)
- link.setAttribute(`href`, url)
- const parentElement =
- document.getElementsByTagName(`head`)[0] ||
- document.getElementsByName(`script`)[0].parentNode
- parentElement.appendChild(link)
+ return new Promise((resolve, reject) => {
+ if (typeof document === `undefined`) {
+ reject()
+ return
+ }
+
+ const link = document.createElement(`link`)
+ link.setAttribute(`rel`, `prefetch`)
+ link.setAttribute(`href`, url)
+
+ link.onload = resolve
+ link.onerror = reject
+
+ const parentElement =
+ document.getElementsByTagName(`head`)[0] ||
+ document.getElementsByName(`script`)[0].parentNode
+ parentElement.appendChild(link)
+ })
}
+
const xhrPrefetchStrategy = function(url) {
- const req = new XMLHttpRequest()
- req.open(`GET`, url, true)
- req.withCredentials = true
- req.send(null)
+ return new Promise((resolve, reject) => {
+ const req = new XMLHttpRequest()
+ req.open(`GET`, url, true)
+ req.withCredentials = true
+
+ req.onload = () => {
+ if (req.status === 200) {
+ resolve()
+ } else {
+ reject()
+ }
+ }
+
+ req.send(null)
+ })
}
const supportedPrefetchStrategy = support(`prefetch`)
@@ -38,11 +59,19 @@ const supportedPrefetchStrategy = support(`prefetch`)
const preFetched = {}
const prefetch = function(url) {
- if (preFetched[url]) {
- return
- }
- preFetched[url] = true
- supportedPrefetchStrategy(url)
+ return new Promise(resolve => {
+ if (preFetched[url]) {
+ resolve()
+ return
+ }
+
+ supportedPrefetchStrategy(url)
+ .then(() => {
+ resolve()
+ preFetched[url] = true
+ })
+ .catch(() => {}) // 404s are logged to the console anyway
+ })
}
export default prefetch
diff --git a/packages/gatsby/cache-dir/production-app.js b/packages/gatsby/cache-dir/production-app.js
index 0770164274baa..a3d51f0579a20 100644
--- a/packages/gatsby/cache-dir/production-app.js
+++ b/packages/gatsby/cache-dir/production-app.js
@@ -15,7 +15,6 @@ window.___emitter = emitter
import PageRenderer from "./page-renderer"
import asyncRequires from "./async-requires"
import loader, { setApiRunnerForLoader } from "./loader"
-import loadDirectlyOr404 from "./load-directly-or-404"
import EnsureResources from "./ensure-resources"
window.asyncRequires = asyncRequires
@@ -85,56 +84,43 @@ apiRunnerAsync(`onClientEntry`).then(() => {
)
}
- loader
- .getResourcesForPathname(browserLoc.pathname)
- .then(resources => {
- if (!resources || resources.page.path === `/404.html`) {
- return loadDirectlyOr404(
- resources,
- browserLoc.pathname + browserLoc.search + browserLoc.hash,
- true
- )
- }
-
- return null
- })
- .then(() => {
- const Root = () =>
- createElement(
- Router,
- {
- basepath: __PATH_PREFIX__,
- },
- createElement(RouteHandler, { path: `/*` })
- )
+ loader.getResourcesForPathname(browserLoc.pathname).then(() => {
+ const Root = () =>
+ createElement(
+ Router,
+ {
+ basepath: __PATH_PREFIX__,
+ },
+ createElement(RouteHandler, { path: `/*` })
+ )
- const WrappedRoot = apiRunner(
- `wrapRootElement`,
- { element: },
- ,
- ({ result }) => {
- return { element: result }
- }
- ).pop()
+ const WrappedRoot = apiRunner(
+ `wrapRootElement`,
+ { element: },
+ ,
+ ({ result }) => {
+ return { element: result }
+ }
+ ).pop()
- let NewRoot = () => WrappedRoot
+ let NewRoot = () => WrappedRoot
- const renderer = apiRunner(
- `replaceHydrateFunction`,
- undefined,
- ReactDOM.hydrate
- )[0]
+ const renderer = apiRunner(
+ `replaceHydrateFunction`,
+ undefined,
+ ReactDOM.hydrate
+ )[0]
- domReady(() => {
- renderer(
- ,
- typeof window !== `undefined`
- ? document.getElementById(`___gatsby`)
- : void 0,
- () => {
- apiRunner(`onInitialClientRender`)
- }
- )
- })
+ domReady(() => {
+ renderer(
+ ,
+ typeof window !== `undefined`
+ ? document.getElementById(`___gatsby`)
+ : void 0,
+ () => {
+ apiRunner(`onInitialClientRender`)
+ }
+ )
})
+ })
})
diff --git a/yarn.lock b/yarn.lock
index 3404d92419ea6..a543e687c4475 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9862,6 +9862,11 @@ icss-utils@^2.1.0:
dependencies:
postcss "^6.0.1"
+idb-keyval@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-3.1.0.tgz#cce9ed320734446784d52ed398c4b075a4273f51"
+ integrity sha512-iFwFN5n00KNNnVxlOOK280SJJfXWY7pbMUOQXdIXehvvc/mGCV/6T2Ae+Pk2KwAkkATDTwfMavOiDH5lrJKWXQ==
+
ieee754@^1.1.4:
version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"