Для начала вам нужно получить обе ваши статьи, а также ваши проекты в запросе graphql, который вы получили. Вы можете использовать двоеточие, чтобы переименовать часть вашего запроса. Я добавил articles:
перед вашей отметкой allMarkdown. В полученном JSON allMarkdownRemark теперь будет называться «article». Вы можете увидеть это в цикле forEach, который теперь перебирает «result.data.articles». Я также добавил запрос для нужного объекта «проекты». Переименование их в статьи и проекты позволяет нам легко перебирать каждую статью и каждый проект и создавать правильные страницы для этих объектов.
Запрос проектов теперь является точной копией запроса статей. На самом деле вы должны предоставить здесь запрос, который возвращает только проекты, но я не знаю, где у вас они есть. Затем создайте отдельные циклы для проектов и статей, в которых вы создаете правильные страницы.
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
graphql(`{
articles: allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
projects: allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}`).then(result => {
// In this loop we only take the articles returned by the query, and
// pass them to the src/templates/article.js component.
result.data.articles.edges.forEach(({ node }) => {
createPage({
// Rather than prepending every slug with '/article' in the
// createNodeField call, you can add it here to get more
// flexibility, and to allow different types to have different
// path prefixes.
path: `article/${node.fields.slug}`,
component: path.resolve(`./src/templates/article.js`),
context: {
slug: node.fields.slug,
},
})
})
// In this loop we do the same thing, only with the projects this
// time, and passing them to the project.js component I'm assuming
// you have. I've prepended the path with 'project/' to separate
// the projects from the articles.
result.data.projects.edges.forEach(({ node }) => {
createPage({
path: `project/${node.fields.slug}`,
component: path.resolve(`./src/templates/project.js`),
context: {
slug: node.fields.slug,
},
})
})
resolve()
})
})
};
Я добавил некоторые отступы, чтобы было легче рассуждать. Возможно, по пути я допустил некоторые синтаксические ошибки, так что остерегайтесь этого.
Я заметил, что в вашем вызове onCreateNode
вы устанавливаете порцию каждого файла уценки на «article / $ {slug}». Если ваши проекты также являются файлами уценки, вы не должны этого делать, потому что это также даст вашим файлам уценки, которые начинаются с '/ article'. В приведенном выше коде я установил правильный путь в вызове createPage, а не в createNodeField.
Одна вещь, которую вы должны иметь в виду, это то, что если у вас есть как ваши статьи, так и ваши проекты в качестве уценкифайлы, ваш запрос будет трудно разобрать их. Я обычно исправляю это, добавляя поле 'type' к frontmatter. Таким образом, в вашем случае вы добавите: type: article
к frontmatter всех ваших статей и type: project
для всех ваших проектов. Часть frontmatter - это часть в верхней части файла уценки, между тремя штриховыми линиями:
---
type: article
name: something
etc, etc...
---
Вы можете отфильтровать файлы уценки следующим образом:
graphql(`query {
projects: allMarkdownRemark ( filter: {frontmatter: { type: { eq: "project" } } } ) {
edges {
node {
fields {
slug
}
}
}
}
}`);
Это вернеттолько файлы уценки, которые имеют тип проекта. Сделайте то же самое для ваших статей. Если вы используете Netlify CMS, вы можете добавить скрытое поле для автоматического добавления правильного типа, чтобы облегчить фильтрацию.
Возможно, вы захотите изменить обещание на асинхронный / ожидающий вызов. Это необязательно, но, на мой взгляд, это намного облегчает чтение. Посмотрите учебник Гэтсби здесь https://www.gatsbyjs.org/tutorial/part-seven/#creating-pages для примера async / await в API createPages.