Гэтсби: несколько типов контента - PullRequest
0 голосов
/ 09 мая 2018

Я пытаюсь набрать скорость на Гэтсби и добиться больших успехов в демонстрациях, но наталкиваюсь на стену с тем, что, на мой взгляд, является относительно распространенным и простым вариантом использования. Мне бы хотелось иметь несколько типов контента, которые я могу написать в Markdown, у каждого из которых есть свой Frontmatter, и у каждого свой шаблон.

Например, мне нужен тип контента BlogPost и тип контента Project:

Тип содержимого BlogPost

---
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 только из одного из источников.

Есть ли более простой способ иметь несколько типов контента?

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Добавление моего ответа, основанного на @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
        }
      }
    }
  }
}
0 голосов
/ 20 июня 2018

Определите различные источники в gatsby-config и поместите свое содержимое в разные каталоги, такие как src/projects и scr/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 tracker tracker

примечание: вы не должны напрямую мутировать узел экземпляр в gatsby-node, а вместо этого использовать createNodeField. Если вы знаете, как фильтровать в GraphQL, используя пользовательские поля, добавьте к этому ответу!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...