盖茨比:多种内容类型
Posted
技术标签:
【中文标题】盖茨比:多种内容类型【英文标题】:Gatsby: Multiple Content Types 【发布时间】:2018-10-18 22:18:37 【问题描述】:我试图跟上 Gatsby 的速度并在演示中取得了巨大的成功,但我觉得这是一个相对常见且简单的用例。我希望有多种可以在 Markdown 中编写的内容类型,每种都有不同的 Frontmatter,每种都有不同的模板。
例如,我想要一个 BlogPost 内容类型和一个 Project 内容类型:
博文内容类型
---
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
中做一些骇人听闻的事情:
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()
)
)
;
我现在遇到的问题是,由于 frontmatter 不一致,看来 GraphQL 仅从其中一个来源获取 frontmatter 模式。
有没有更简单的方法来拥有多种内容类型?
【问题讨论】:
【参考方案1】:在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 中进行过滤,请添加到此答案中!
【讨论】:
【参考方案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
【讨论】:
以上是关于盖茨比:多种内容类型的主要内容,如果未能解决你的问题,请参考以下文章