我试图加快Gatsby的速度,并在演示中取得了巨大的成功,但是我遇到了一个相对常见且简单的用例。我希望有多种内容类型可以在Markdown中编写,每种内容类型都有不同的Frontmatter,每种类型都有不同的模板。
例如,我想要一个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
中做一些hacky:
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()
})
})
};
我现在遇到的问题是,由于前端不一致,看起来GraphQL只从其中一个源获取前端模式。
是否有更简单的方法来拥有多种内容类型?
答案 0 :(得分:3)
在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 issue tracker
的评论 注意:您不应该直接更改gatsby-node
中的 node 实例,而应使用createNodeField
。如果您知道如何使用自定义字段在graphql中进行过滤,请添加至此答案!
答案 1 :(得分:2)
添加我的答案,该答案基于@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
}
}
}
}
}