From 818301227f6f8946e2130a43b75f3d685bc32b70 Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Wed, 10 Mar 2021 23:47:08 +0100 Subject: [PATCH] fix(gatsyby): improve error messages for errors outside of react" (#30031) --- .../cache-dir/__tests__/ensure-resources.tsx | 3 +++ packages/gatsby/cache-dir/ensure-resources.js | 25 ++++++++++++++----- packages/gatsby/cache-dir/loader.js | 22 ++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/packages/gatsby/cache-dir/__tests__/ensure-resources.tsx b/packages/gatsby/cache-dir/__tests__/ensure-resources.tsx index 0613effcbdb04..8d5841c614fbd 100644 --- a/packages/gatsby/cache-dir/__tests__/ensure-resources.tsx +++ b/packages/gatsby/cache-dir/__tests__/ensure-resources.tsx @@ -4,6 +4,9 @@ import { render, getNodeText, cleanup } from "@testing-library/react" jest.mock(`../loader`, () => { return { + PageResourceStatus: { + Error: `error`, + }, loadPageSync(path: string): { loadPageSync: boolean; path: string } { return { loadPageSync: true, path } }, diff --git a/packages/gatsby/cache-dir/ensure-resources.js b/packages/gatsby/cache-dir/ensure-resources.js index c3232c1fab076..80bbb8d8dcdf9 100644 --- a/packages/gatsby/cache-dir/ensure-resources.js +++ b/packages/gatsby/cache-dir/ensure-resources.js @@ -8,13 +8,18 @@ class EnsureResources extends React.Component { const { location, pageResources } = props this.state = { location: { ...location }, - pageResources: pageResources || loader.loadPageSync(location.pathname), + pageResources: + pageResources || + loader.loadPageSync(location.pathname, { withErrorDetails: true }), } } static getDerivedStateFromProps({ location }, prevState) { if (prevState.location.href !== location.href) { - const pageResources = loader.loadPageSync(location.pathname) + const pageResources = loader.loadPageSync(location.pathname, { + withErrorDetails: true, + }) + return { pageResources, location: { ...location }, @@ -82,12 +87,20 @@ class EnsureResources extends React.Component { } render() { - if (process.env.NODE_ENV !== `production` && !this.state.pageResources) { - throw new Error( - `EnsureResources was not able to find resources for path: "${this.props.location.pathname}" + if ( + process.env.NODE_ENV !== `production` && + (!this.state.pageResources || + this.state.pageResources.status === PageResourceStatus.Error) + ) { + const message = `EnsureResources was not able to find resources for path: "${this.props.location.pathname}" This typically means that an issue occurred building components for that path. Run \`gatsby clean\` to remove any cached elements.` - ) + if (this.state.pageResources?.error) { + console.error(message) + throw this.state.pageResources.error + } + + throw new Error(message) } return this.props.children(this.state) diff --git a/packages/gatsby/cache-dir/loader.js b/packages/gatsby/cache-dir/loader.js index f42da55644d5f..1a1e227718bde 100644 --- a/packages/gatsby/cache-dir/loader.js +++ b/packages/gatsby/cache-dir/loader.js @@ -348,12 +348,22 @@ export class BaseLoader { return inFlightPromise } - // returns undefined if loading page ran into errors - loadPageSync(rawPath) { + // returns undefined if the page does not exists in cache + loadPageSync(rawPath, options = {}) { const pagePath = findPath(rawPath) if (this.pageDb.has(pagePath)) { - const pageData = this.pageDb.get(pagePath).payload - return pageData + const pageData = this.pageDb.get(pagePath) + + if (pageData.payload) { + return pageData.payload + } + + if (options?.withErrorDetails) { + return { + error: pageData.error, + status: pageData.status, + } + } } return undefined } @@ -546,7 +556,9 @@ export const publicLoader = { getResourceURLsForPathname: rawPath => instance.getResourceURLsForPathname(rawPath), loadPage: rawPath => instance.loadPage(rawPath), - loadPageSync: rawPath => instance.loadPageSync(rawPath), + // TODO add deprecation to v4 so people use withErrorDetails and then we can remove in v5 and change default behaviour + loadPageSync: (rawPath, options = {}) => + instance.loadPageSync(rawPath, options), prefetch: rawPath => instance.prefetch(rawPath), isPageNotFound: rawPath => instance.isPageNotFound(rawPath), hovering: rawPath => instance.hovering(rawPath),