我正在使用无头WordPress作为数据源的Gatsbyjs Web。我不想在/ pages中静态生成所有页面,而是在im gatsby-node.js中通过allPages / allPosts查询进行映射,并使用createPage
API将数据发送到page / post模板。
但是我的页面有点复杂,它们似乎需要非常不同的查询(请参阅。
这里的最佳做法是什么?我应该为每个页面创建一个模板并将数据直接映射到其中吗?
答案 0 :(得分:2)
是的,你打钉子了。您必须为要生成的每种页面类型生成模板/页面。
您只需要创建不同的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
中找到。
承诺用例
如果您的网站或项目较小,则前一种情况可能会起作用,但是如果您的项目不断发展,那么在如此多的行中查找信息将变得很困难。因此,我用来创建promises来存储该信息。在我的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;
请注意,可以通过多种方式重构代码,这只是为了展示您能够执行的另一种方法。
我认为Promise方法更加语义化和整洁,但在每种情况下您都可以使用所需的任何东西。
参考: