如果在渲染过程中该页面最终抛出该页面,是否可以跳过该页面的创建?

时间:2020-01-24 16:57:35

标签: gatsby

如果在渲染过程中该页面最终抛出该页面,是否可以跳过该页面的创建?

此页面为created programmatically via gatsby-node createPage,页面查询(来自我们的CMS)中的数据很可能导致其抛出错误。

我不想由于一个不良页面而停止构建,因此理想情况下不会创建该页面或将一个后备页面放在其位置(并且错误事件将记录到Sentry或类似文件中)。 / p>

关于如何实现这一目标的任何想法?


编辑:我没有足够清楚地阐明我的问题,所以我想添加一些有关我要解决的问题以及原因的背景。

我正在尝试捕获的错误发生在构建期间的页面呈现期间。发生此错误是因为我正在尝试呈现的组件假定了一些与数据无关的信息正确(但应该正确)。

例如,假设我正在为网站上的所有产品创建许多页面。该组件期望每个产品都具有imagesSizes并在渲染过程中调用imagesSizes.split(',')。由于imagesSizespage querynull,因此整个组件都会引发错误并中断构建。

就像@EliteRaceElephant一样,我尝试使用React Error Boundaries ,不幸的是,它们不适用于SSR(在构建期间由Gatsby使用)。因此,即使我将组件包装在错误边界内,它仍然最终会破坏构建。

最后一点,我在上面给出的示例只是我遇到的一种情况,即数据损坏并破坏了构建。

我要实现的是一个简单的后备页面,用于在构建过程中的渲染过程中发生任何任意错误。当我对数据所做的某些假设不正确时,我的理想解决方案甚至允许我故意throw错误(因为我宁愿向用户发送错误页面,而不是向他们显示错误数据的页面)


从历史上看,当我在盖茨比之外完成SSR时,我只需将对ReactDOMServer.renderToString的整个调用包装在try catch块中,然后在{ {1}}块。

与盖茨比等效的是什么?

1 个答案:

答案 0 :(得分:3)

您可以正常处理错误,因为graphQL查询是作为一个承诺返回的。如果承诺无法解决,请处理引发的错误,并继续构建您的页面。

来自Gatsby node API documentation

const path = require(`path`)
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)

  return graphql(`
    query loadPagesQuery ($limit: Int!) {
      allMarkdownRemark(limit: $limit) {
        edges {
          node {
            frontmatter {
              slug
            }
          }
        }
      }
    }
  `, { limit: 1000 }).then(result => {
    if (result.errors) {
      throw result.errors

      // ##### Handle your ERROR here #######
      // send to sentry, try another query, etc
      // or pass an empty result object so no pages are created but the build continues

    }
    result.data.allMarkdownRemark.edges.forEach(edge => {
      createPage({
        path: `${edge.node.frontmatter.slug}`,
        component: blogPostTemplate,
        context: {},
      })
    })
  })
}

编辑#1

您的错误发生在页面模板中。您可以使用error boundaries以React方式处理组件中的错误。在组件周围包裹一个错误边界,并处理其中的所有错误。错误边界也可以启动错误页面的构建。您也可以处理页面查询在PageTemplate组件中返回的任何内容。

<PageTemplate>
  <ErrorBoundary>
    <YourContent />
  </ErrorBoundary>
</Page Template>

编辑#2

我现在了解问题了,可以提出一些建议。我认为没有一个简单的解决方案,因为它涉及到React和Gatsby的内部工作原理:

尝试捕获模板的非React部分。使用包装函数尝试捕获错误。

我假设您的JSX代码中包含以下内容:

<PageTemplate>
  { imagesSizes.split(',') // do whatever and break the build }
</PageTemplate>

相反,请首先使用try catch通过函数运行所有代码中断变量。如果有任何函数捕获,则呈现错误页面。为此,您可能需要一个类基础组件。在调用render()

之前放置函数
let pageThrows = false;

const imageSizesSplitCheck = (images) => {
  try {
    imagesSizes.split(',') // throw error
  } catch {
    pageThrows = true; // outside of the JSX flow you can still catch errors while serverside renddering
  }
}
// more try catch functions

if (pageThrows) {
  // render error page
} else {
  // render default page 
}


处理数据的极端情况是一种好的编码习惯,这样就不会引发异常。我认为它甚至在“清洁代码”书中也提到过。否则,您将误用正常程序流程的异常。例外应该保留。