You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数
  • 缓存残留旧数据,导致构建时读取到异常的节点信息

解决方案

  1. 验证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。

  2. 检查slug生成逻辑:确认onCreateNode中的node.internal.type是否正确,部分Gatsby版本中MDX节点的类型是MDX(大写),而非Mdx,可调整为:

    if (node.internal.type === `MDX`) {
        // ...生成slug逻辑
    }
    
  3. 过滤异常节点:在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 }
        })
    })
    
  4. 验证文件系统配置:确认gatsby-source-filesystem的path覆盖了所有MDX文件所在目录,若路径错误会导致部分文件没被抓取。

  5. 清理缓存:执行gatsby clean清除旧缓存,再重新运行npm run build。

内容的提问来源于stack exchange,提问作者Marco Sousa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:48:14