我正在用无头WordPress作为数据源开发Gatsbyjs网站。我不想在/pages中静态地生成所有页面,而是在imGatsby-node.js中通过allPages / allPosts查询和使用createPage API向页面/post模板发送数据。
但是我的页面有点复杂,它们似乎需要非常不同的查询( acf..。)
这里的最佳做法是什么?我是否应该为每个页面创建一个模板,并将数据直接映射到这些页面中?
发布于 2020-03-25 15:19:47
是的,你打到钉子了。您必须为要生成的每一种类型的页面生成模板/页。
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中找到。
承诺用例
如果你有一个小的网站或项目,以前的情况可能有效,但是如果你的项目增长,在这么多行中找到信息就会变成地狱。因此,我使用创建承诺来存储这些信息。在我的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;请注意,代码可以在许多方面进行重构,这仅仅是为了展示您能够做的另一种方法。
我认为承诺的方式更具有语义性和清晰性,但在每种情况下都由您使用所需的任何东西。
参考资料:
https://stackoverflow.com/questions/60851427
复制相似问题