使用File System Route API创建页面时Gatsby静态HTML构建报错
问题根因
你遇到的问题本质是Gatsby的文件系统路由(FileSystem Route API)默认会把所有MDX节点匹配到所有符合命名规则的{mdx.slug}.js模板上。gatsby develop是按需渲染,你没有访问错误生成的路径就不会触发报错,而gatsby build是全量生成所有匹配到的页面,当博客MDX被错误匹配到服务页模板渲染时,如果模板依赖的字段博客MDX不存在,就会抛出静态HTML构建失败的错误。
解决方案
方案1:修改路由模板文件名,增加匹配过滤(最便捷)
Gatsby 4及以上版本的文件系统路由支持在路由参数中添加过滤规则,直接限定每个模板匹配的MDX来源:
- 把
pages/blog/{mdx.slug}.js重命名为pages/blog/{mdx(sourceInstanceName: {eq: "blog"}).slug}.js - 把
pages/services/{mdx.slug}.js重命名为pages/services/{mdx(sourceInstanceName: {eq: "services"}).slug}.js
修改后每个模板只会匹配对应sourceInstanceName的MDX节点,不会再出现交叉匹配的问题。
方案2:改用gatsby-node.js手动生成页面(可控性最高)
如果不想修改文件名,可以放弃自动路由,通过gatsby-node.js的createPagesAPI手动生成页面,完全控制每个MDX对应的模板和路径:
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // 查询所有MDX节点信息 const result = await graphql(` query { allMdx { nodes { id slug sourceInstanceName } } } `) // 遍历生成对应页面 result.data.allMdx.nodes.forEach(node => { if (node.sourceInstanceName === 'blog') { createPage({ path: `/blog/${node.slug}/`, component: require.resolve('./src/pages/blog/{mdx.slug}.js'), context: { id: node.id } }) } if (node.sourceInstanceName === 'services') { createPage({ path: `/services/${node.slug}/`, component: require.resolve('./src/pages/services/{mdx.slug}.js'), context: { id: node.id } }) } }) }
添加完上述代码后,删除原来的自动路由模板或者把模板移到src/templates目录下避免重复生成即可。
临时排查方案
如果需要先确认是不是交叉匹配导致的问题,可以在构建命令后加--verbose参数运行gatsby build --verbose,查看每个页面对应的生成模板,确认错误路径/services/blog-post-1/是否确实是调用了服务页模板生成。
内容的提问来源于stack exchange,提问作者Sam Quayle
相关产品推荐
相关产品推荐

