【问题标题】:Gatsby: Multiple Content Types盖茨比:多种内容类型
【发布时间】:2018-10-18 22:18:37
【问题描述】:

我试图跟上 Gatsby 的速度并在演示中取得了巨大的成功,但我觉得这是一个相对常见且简单的用例。我希望有多种可以在 Markdown 中编写的内容类型,每种都有不同的 Frontmatter,每种都有不同的模板。

例如,我想要一个 BlogPost 内容类型和一个 Project 内容类型:

博文内容类型

---
title: My Post
date: "2017-09-21"
---

This is my blog body

项目内容类型

---
projectName: My Project
startDate: "2017-09-21"
endDate: "2017-10-21"
---

This is my project description

然后为了让它们在相关模板中呈现,我不得不使用正则表达式在gatsby-node.js 中做一些骇人听闻的事情:

const components = {
  blog: `./src/templates/blog-post.js`,
  projects: `./src/templates/project-post.js`,
}
exports.createPages = ({ graphql, boundActionCreators }) => {
  const { createPage } = boundActionCreators
  RE_DIR = new RegExp("\/pages\/([a-z]+)\/.*\.md$");
  return new Promise((resolve, reject) => {
    graphql(`
      {
        allMarkdownRemark {
          edges {
            node {
              fileAbsolutePath
              fields {
                slug
              }
            }
          }
        }
      }
    `).then(result => {
      result.data.allMarkdownRemark.edges.forEach(({ node }) => {
        // console.log(RE_DIR.exec(node.fileAbsolutePath))


        const postType = RE_DIR.exec(node.fileAbsolutePath)[1]

        if (postType) {
          createPage({
            path: node.fields.slug,
            component: path.resolve(components[postType]),
            context: {
              // Data passed to context is available in page queries as GraphQL variables.
              slug: node.fields.slug,
            },
          })
        }


      })
      resolve()
    })
  })
};

我现在遇到的问题是,由于 frontmatter 不一致,看来 GraphQL 仅从其中一个来源获取 frontmatter 模式。

有没有更简单的方法来拥有多种内容类型?

【问题讨论】:

    标签: reactjs graphql gatsby


    【解决方案1】:

    gatsby-config 中定义不同的来源,并将您的内容放在不同的目录中,例如src/projectsscr/blog-posts

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

    那么你可以根据gatsby-node中的源名称创建字段类型

    exports.onCreateNode =({ node, getNode, boundActionCreators }) => {
        if (node.internal.type === 'MarkdownRemark') {
            const { createNodeField } = boundActionCreators;
            node.collection = getNode(node.parent).sourceInstanceName;
        }
    }
    

    现在您可以过滤您的 graphql 查询以收集内容,并且您可以根据内容类型生成特定模板。

    query postsOnly {
        allMarkdownRemark(filter: { collection: { eq: "posts" } }) {
            edges {
                node {
                    id
                    collection
                }
            }
        }
    }
    

    代码基于github issue tracker上的这条评论

    注意:你不应该直接改变gatsby-node中的node实例,而应该使用createNodeField。如果您知道如何使用自定义字段在 graphql 中进行过滤,请添加到此答案中!

    【讨论】:

      【解决方案2】:

      添加我基于@nicokant 的答案,但似乎有所改变。我在这里也使用 mdx,但如果您使用的是 MarkdownRemark,则只需换掉即可:

      给每个来源一个名称选项:

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

      然后在创建节点时,为其分配一个自定义字段:

      exports.onCreateNode = ({ node, actions, getNode }) => {
        const { createNodeField } = actions
        if (node.internal.type === `MarkdownRemark` || node.internal.type === `Mdx`) {
          createNodeField({
            name: `collection`,
            node,
            value: getNode(node.parent).sourceInstanceName
          });
        })
      };
      

      然后可以根据自定义字段查询:

      query {
        allMdx(filter: { fields: { collection: { eq: "post"}}}) {
          edges {
            node {
              fields {
                collection
              }
              frontmatter {
                title
              }
            }
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-12-16
        • 2018-10-14
        • 2020-05-23
        • 2019-06-17
        • 2020-04-20
        • 1970-01-01
        • 1970-01-01
        • 2020-02-02
        • 2021-04-25
        相关资源
        最近更新 更多