Gatsby构建时提示未提供必填变量$slug,开发环境正常
Gatsby构建时MDX页面查询slug缺失问题
问题场景
使用MDX文件搭建Gatsby站点,npm run develop下站点运行正常,但执行npm run build时抛出错误:
Variable "$slug" of required type "String!" was not provided.
错误指向src/templates/blog/blog.js文件。
相关代码片段
blog.js中的查询
export const query = graphql` query ( $slug: String! ) { mdx( fields: { slug: { eq: $slug } } ) { frontmatter { title details date(formatString: "LL") tags } body } }` export default function Blog(props) { return (...content...) }
gatsby-config.js相关配置
module.exports = { siteMetadata: { title: '...', author: '...' }, plugins: [..., {resolve: 'gatsby-source-filesystem', options: { name:'src', path: `${__dirname}/src/` } ...
gatsby-node.js代码
/* pathing via node.js; for path.basename*/ const path = require('path') /* node function that runs when node is created*/ module.exports.onCreateNode = ({node, actions}) => { const {createNodeField} = actions if (node.internal.type === `Mdx`) { const slug = path.basename(node.fileAbsolutePath, '.mdx') createNodeField({ node, name: 'slug', value: slug }) } } // Creating blog pages // 1.Get path to template // 2.Get markdown data // 3.create new pages module.exports.createPages = async ({graphql, actions}) => { const{ createPage } = actions const blogTemplate = path.resolve('./src/templates/blog.js') const res = await graphql(` query { allMdx { edges { node { fields { slug } } } } } `) res.data.allMdx.edges.forEach((edge) => { createPage({ component: blogTemplate, path: `/blog/${edge.node.fields.slug}`, context: { slug: edge.node.fields.slug } }) }) }
问题原因
开发模式下Gatsby按需渲染页面,只有访问对应博客页面时才会执行查询;但构建阶段Gatsby会预渲染所有页面,此时若存在以下情况就会报错:
- 某个MDX文件未被正确生成slug(比如
onCreateNode的判断逻辑失效,或文件路径异常) createPages中的查询未获取到所有MDX节点,导致部分页面的context缺失slug参数- 缓存残留旧数据,导致构建时读取到异常的节点信息
解决方案
验证createPages查询结果:在
createPages函数中添加日志,确认所有MDX节点都有slug:res.data.allMdx.edges.forEach((edge) => { console.log('Processing slug:', edge.node.fields?.slug) createPage({ component: blogTemplate, path: `/blog/${edge.node.fields.slug}`, context: { slug: edge.node.fields.slug } }) })运行
gatsby build前查看日志,若有undefined的slug,说明对应的MDX文件没生成slug。检查slug生成逻辑:确认
onCreateNode中的node.internal.type是否正确,部分Gatsby版本中MDX节点的类型是MDX(大写),而非Mdx,可调整为:if (node.internal.type === `MDX`) { // ...生成slug逻辑 }过滤异常节点:在
createPages中跳过没有slug的节点,避免创建无效页面:res.data.allMdx.edges.forEach((edge) => { const slug = edge.node.fields?.slug if (!slug) return createPage({ component: blogTemplate, path: `/blog/${slug}`, context: { slug } }) })验证文件系统配置:确认
gatsby-source-filesystem的path覆盖了所有MDX文件所在目录,若路径错误会导致部分文件没被抓取。清理缓存:执行
gatsby clean清除旧缓存,再重新运行npm run build。
内容的提问来源于stack exchange,提问作者Marco Sousa
相关产品推荐
相关产品推荐

