如何在Gatsby中使用mdx创建多个节点类型



我正在尝试使用mdx(而不是remark(在Gatsby中创建多个内容类型。我在筛选处理备注的旧方法和mdx的新方法时遇到了困难。我已经在各种教程中看到了查询allXYZ根节点的多个实例,但我很难理解这些实例最初是如何创建的。我知道在某些情况下,Gatsby或插件会创建这些节点(allMdxallMarkdownRemarkallFile等(,但我想学习如何使用该内容类型的相关字段节点创建类似allPostsallProjects的内容。

我的最终目标是实现以下目标:

  • 将mdx内容存储在指示其内容类型的不同文件夹(postsprojectspages(中
  • src/pages中有一个匹配的文件夹结构,每个文件夹中都有一个index.js文件(帖子、项目或页面的登录页(和一个使用新语法{type.field}.js的模板文件
  • 能够在各自的index.js文件中查询allPosts/allProjects/allPages,并将这些类型用于模板文件({Post.slug}.js{Project.slug}.js等(
  • 模板文件将以与基本教程中使用allMdxmdx相同的方式查询子节点(postprojectpage(
  • 不需要使用gatsby-node.js中的createPages挂钩,因为gatsby-source-filesystem应该用上面的结构为我做这件事

我发现这篇stackoverflow帖子提出了一个类似的问题,但答案似乎意味着这些自定义节点(allPosts等(应该在你设置这样的插件选项时自动创建:

{
    resolve: `gatsby-source-filesystem`,
    options: {
        name: `posts`,
        path: `${__dirname}/content/posts`,
    },
},

然而,这对我来说并不奏效。当我使用__graphql接口时,这些节点不存在,如果我试图以任何方式查询它们,我会得到一个错误(注意:我曾尝试使用projectsProjectproject等命名模板文件,但没有成功(:

PageCreator: Tried to create pages from the collection builder.
Unfortunately, the query came back empty. There may be an error in your query:
Cannot query field "allProjects" on type "Query".
File: src/pages/projects/{projects.slug}.js

我还找到了这本盖茨比指南,它似乎解决了我的部分问题,但我不明白如何在本地获取数据,而不是通过他们使用的API请求。我还认为这可能会使一些非常简单的东西过于复杂,而这些东西本应与mdx和文件系统插件一起使用?不确定!

我觉得我错过了一些基本的东西。我还是盖茨比的新手,所以我完全有可能错了,认为这会按照我的意愿进行,但我花了几个小时试图弄清楚这一点,认为是时候最终寻求帮助了,哈哈。

任何建议都将不胜感激!!

您可以尝试这个Gatsby插件https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx-source-name/?=mdx

我什么时候使用这个插件?如果您正在使用gatsby源文件系统的多个实例,则此插件非常有用,因为它将允许您从Mdx节点上的源插件中查询名称字段。

plugins: [
`gatsby-plugin-mdx-source-name` ,
    {
        resolve: `gatsby-source-filesystem` ,
        options: {
            path: `${__dirname}/src/blog` ,
            name: `blog` // this name will be added to the Mdx nodes
        }
    }
]

源名称现在可以通过GraphQL:进行查询

const query = graphql`
query {
    allMdx(){
        nodes {
           id
           fields {
               source
           }
        }
    }
}`

例如,如果您想在页面创建时通过这个新的源字段进行筛选,您可以执行以下操作:

// gatsby-node.js
exports.createPages = ({actions, graphql}) => {
    const {createPage} = actions
    
    // query for all Mdx pages
    const query = graphql(`
        query {
            allMdx(){
                nodes {
                    fields {
                        source
                    }
                    frontmatter {
                        slug
                    }
                }
            }
        }
    `)
    return query.then(result => {
        // filter by source name "blog"
        const posts = result.data.allMdx.nodes.filter(node => node.fields.source === 'blog')
        posts.forEach(node => {
            createPage({
                path: `/blog/${node.frontmatter.slug}`,
                component: path.resolve('src/templates/blog-post.js'),
                context: {
                    slug: node.frontmatter.slug
                }
            })
        })
    })
}

使用onCreateNode 创建自己的自定义类型

https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/#onCreateNode

https://www.gatsbyjs.com/docs/reference/graphql-data-layer/schema-customization/

我的解决方案是使用fileAbsolutePath根据我的文件所在的文件夹来确定.mdx文件是页面还是帖子等。

if (node.internal.type == 'Mdx' && node.fileAbsolutePath.indexOf('pages') !== -1) {
            actions.createNode({
                id: createNodeId(`MdxPage-${node.id}`),
                parent: node.id,
                internal: {
                    type: `MdxPage${node.internal.type}`,
                    contentDigest: node.internal.contentDigest,
                },
            })
        } 

另一个选项是按照您所描述的进行文件夹结构,而不是使用allMdx基于fileAbsolutePath:进行过滤

allMdx(
    sort: { fields: frontmatter___date, order: DESC }
    filter: { fileAbsolutePath: {regex: "/content/projects/"} }
  )  

或者,如果您希望在使用别名的同一查询中多次调用allMdx:

  projects: allMdx(
    filter: { fileAbsolutePath: {regex: "/content/posts/"} }
  ) { ... }
  posts: allMdx(
    filter: { fileAbsolutePath: {regex: "/content/projects/"} }
  ) { ... } 

相关内容

  • 没有找到相关文章

最新更新