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

如何在Gatsby中定义node type 实现不同MDX内容的自定义集合路由

问题原因

gatsby-source-filesystem配置的name参数只会给对应生成的File节点添加sourceInstanceName标识,不会自动生成自定义节点类型,因此无法直接作为集合路由中的nodeType使用,需要手动创建自定义节点类型来实现需求。

实现步骤

1. 拆分数据源配置(按目录区分内容类型时需要)

如果不同类型的MDX文件存放在独立目录下,先给每个目录单独配置gatsby-source-filesystem,添加对应类型标识:

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: "gatsby-source-filesystem",
      options: {
        path: `${__dirname}/blog`,
        name: "article",
      }
    },
    {
      resolve: "gatsby-source-filesystem",
      options: {
        path: `${__dirname}/projects`,
        name: "project",
      }
    },
    {
      resolve: "gatsby-source-filesystem",
      options: {
        path: `${__dirname}/tags`,
        name: "tag",
      }
    },
    "gatsby-plugin-mdx",
    // 其他插件
  ]
}

2. 手动创建自定义节点类型

在gatsby-node.js中通过onCreateNode钩子,根据MDX文件的归属类型生成对应自定义节点:

// gatsby-node.js
exports.onCreateNode = ({ node, actions, createNodeId, createContentDigest }) => {
  const { createNode, createParentChildLink } = actions

  // 仅处理MDX类型节点
  if (node.internal.type !== "Mdx") return

  // 按目录区分类型的场景:从父File节点取sourceInstanceName标识
  const sourceType = node.parent?.sourceInstanceName
  // 按frontmatter区分类型的场景:替换为 const sourceType = node.frontmatter.type
  let customType, fields

  switch(sourceType) {
    case "article":
      customType = "Article"
      fields = { slug: node.frontmatter.slug || node.slug }
      break
    case "project":
      customType = "Project"
      fields = { slug: node.frontmatter.slug || node.slug }
      break
    case "tag":
      customType = "Tag"
      fields = { id: node.frontmatter.id || node.slug }
      break
    default:
      return
  }

  // 生成自定义类型节点
  const customNode = {
    ...fields,
    mdx: node, // 关联原MDX节点,方便查询内容
    id: createNodeId(`${customType}-${node.id}`),
    parent: node.id,
    internal: {
      type: customType,
      contentDigest: createContentDigest(node),
    }
  }

  createNode(customNode)
  createParentChildLink({ parent: node, child: customNode })
}

3. 按自定义类型创建集合路由

直接使用上面定义的节点类型创建对应路由文件,结构和你需要的完全匹配:

src/pages/
├── index.tsx
├── blog/
│   └── {Article.slug}.tsx
├── projects/
│   └── {Project.slug}.tsx
└── tags/
    └── {Tag.id}.tsx

4. 路由页面数据查询示例

以blog/{Article.slug}.tsx为例,查询对应内容的写法:

import * as React from "react"
import { graphql } from "gatsby"

export default function ArticlePage({ data }) {
  const article = data.article
  return (
    <div>
      <h1>{article.mdx.frontmatter.title}</h1>
      <div>{article.mdx.body}</div>
    </div>
  )
}

export const query = graphql`
  query($id: String!) {
    article(id: { eq: $id }) {
      slug
      mdx {
        frontmatter {
          title
          date
        }
        body
      }
    }
  }
`

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:27:02