gatsby - 如果该页面最终在渲染期间抛出,是否可以在构建期间跳过创建页面?
问题描述
如果该页面最终在渲染期间抛出,是否可以在构建期间跳过创建页面?
此页面是通过 gatsby-node 以编程方式创建createPage
的,并且来自页面查询(来自我们的 CMS)的数据可能是错误的,导致它抛出。
我不想因为一个错误的页面而停止构建,所以理想情况下不会创建该页面或将后备页面放置在它的位置(并且错误事件将被记录到 Sentry 或类似的)。
关于如何实现这一目标的任何想法?
编辑:我没有充分澄清我的问题,所以我想添加一些关于我要解决的问题以及原因的背景信息。
我试图捕捉的错误发生在构建期间渲染页面的过程中。发生此错误是因为我尝试渲染的组件假定数据不正确(但应该是正确的)。
例如,假设我正在为我网站上的所有产品创建许多页面。该组件期望每个产品在渲染期间都有imagesSizes
并调用。imagesSizes.split(',')
因为imagesSizes
来自页面查询null
,所以整个组件会抛出错误并破坏构建。
就像@EliteRaceElephant 建议的那样,我尝试过使用React 错误边界,不幸的是,它们不适用于 SSR(Gatsby 在构建时使用)。因此,即使我将组件包装在错误边界中,它最终仍然会破坏构建。
最后一点,我上面给出的示例只是我遇到的数据错误并破坏构建的情况之一。
我想要实现的是一个简单的后备页面,用于在构建期间渲染期间发生任何任意错误时。当我对数据所做的某些假设不正确时,我的理想解决方案甚至允许我throw
故意出错(因为我宁愿向用户发送错误页面,而不是向他们显示包含错误数据的页面)。
从历史上看,当我在 Gatsby 之外完成 SSR 时,我会简单地将整个调用包装ReactDOMServer.renderToString
在一个try
catch
块中,然后在该块中返回我的后备页面catch
。
盖茨比相当于什么?
解决方案
您可以优雅地处理错误,因为 graphQL 查询是作为承诺返回的。如果承诺无法解决并继续构建您的页面,请处理引发的错误。
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
您的错误发生在页面模板中。您可以使用 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
}
处理数据的边缘情况是一种很好的编码实践,这样就不会引发异常。我认为它甚至在清洁代码书中提到过。否则,您会误用正常程序流程的异常。例外应该仍然是例外。
推荐阅读
- c# - Main window in WPF application is not showing in screen share in skype or teams
- r - 将 slectizeInput 小部件输入与多个 checkboxGroupButtons 小部件输入同步
- sql - 如何在 SQL 中不使用“ORDER BY”进行升序排序
- postgresql - 列索引超出范围
- python - 如何安全地存储 API 密钥和秘密?
- c++ - 将十进制转换为 8 位二进制补码 C++
- c# - 即使文件当前由另一个 Linux App-2(C++) 写入,Linux App-1(C#) 也不会引发文件访问错误
- javascript - 查找后的 Moongose,object.map 未返回键
- json - 如何将大 json 数据与 HTTPoison 一起使用?
- c++ - 捕获队列溢出异常时发生