Да, вы попали в гвоздь. Вы должны сгенерировать шаблоны / страницы для каждого типа страницы, которую вы хотите сгенерировать.
TL; DR
Вам нужно только создать различные действия createPage
и указать их на разных шаблонах / страницах. , Например:
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.fields.slug,
},
})
и
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/tags.js`),
context: {
slug: node.fields.slug,
},
})
Длинная версия
Стандартный вариант использования
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.fields.slug,
},
})
})
}
component
определит, где будут доступны данные для использования и какой шаблон / страница / компонент будет использоваться.
Если вы хотите использовать другой шаблон вместо /blog-post
, вам нужно создать другое действие createPage
, Примерно так:
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
return graphql(`
{
allMarkdownRemark(limit: 1000) {
edges {
node {
id
fields {
slug
}
frontmatter {
tags
templateKey
}
}
}
}
}
`).then(result => {
if (result.errors) {
result.errors.forEach(e => console.error(e.toString()))
return Promise.reject(result.errors)
}
const posts = result.data.allMarkdownRemark.edges
posts.forEach(edge => {
const id = edge.node.id
createPage({
path: edge.node.fields.slug,
tags: edge.node.frontmatter.tags,
component: path.resolve(
`src/templates/blog-post.js`
),
// additional data can be passed via context
context: {
id,
},
})
})
// Tag pages:
let tags = []
// Iterate through each post, putting all found tags into `tags`
posts.forEach(edge => {
if (_.get(edge, `node.frontmatter.tags`)) {
tags = tags.concat(edge.node.frontmatter.tags)
}
})
// Eliminate duplicate tags
tags = _.uniq(tags)
// Make tag pages
tags.forEach(tag => {
const tagPath = `/tags/${_.kebabCase(tag)}/`
createPage({
path: tagPath,
component: path.resolve(`src/templates/tags.js`),
context: {
tag,
},
})
})
})
}
Не вдаваясь в подробности того, что он делает или как (если вам нужно, я могу детализировать ответ), важно то, что вы можете использовать действие createPage
, чтобы определить, сколько страницы, данные и компоненты, которые вам нужны. В этом случае blog-post.js
и tags.js
, которые будут найдены под /blog-post/postSlug
и /tag/tagPath
.
Вариант использования Promise
Если у вас есть маленький сайт или проект, предыдущий случай может сработать, но если ваш проект растет, то становится чертовски найти информацию среди такого количества строк. Поэтому я использую для создания обещаний для хранения этой информации. В моем gatsby-node
:
const postsBuilder = require("./src/build/postsBuilder");
const tagsBuilder = require("./src/build/tagsBuilder");
exports.createPages = async ({graphql, actions}) => {
await Promise.all(
[
postBuilder(graphql, actions),
tagsBuilder(graphql, actions)
]
);
};
Затем, в одном из этих конструкторов:
const path = require('path')
async function postsBuilder(graphql, actions) {
const {createPage} = actions;
const postsQuery= await graphql(`
{
allMarkdownRemark(limit: 1000) {
edges {
node {
id
fields {
slug
}
frontmatter {
tags
templateKey
}
}
}
}
}`);
const resultForms = postsQuery.data.allMarkdownRemark.edges;
resultForms.map(node => {
createPage({
path: node.node.url + '/',
component: whateverYouNeed,
context: {
name: node.node.name,
url: node.node.url
},
})
});
}
module.exports = postsBuilder;
Обратите внимание, что код может быть реорганизован разными способами, это просто показать другой подход того, что вы можете сделать.
Я думаю, что обещанный способ намного более семантичен c и чист, но вы должны использовать все, что вам нужно в каждом случае.
Ссылки:
- Первый запрос
- Второй запрос