我正在尝试使用mdx(而不是remark(在Gatsby中创建多个内容类型。我在筛选处理备注的旧方法和mdx的新方法时遇到了困难。我已经在各种教程中看到了查询allXYZ
根节点的多个实例,但我很难理解这些实例最初是如何创建的。我知道在某些情况下,Gatsby或插件会创建这些节点(allMdx
、allMarkdownRemark
、allFile
等(,但我想学习如何使用该内容类型的相关字段节点创建类似allPosts
或allProjects
的内容。
我的最终目标是实现以下目标:
- 将mdx内容存储在指示其内容类型的不同文件夹(
posts
、projects
、pages
(中 - 在
src/pages
中有一个匹配的文件夹结构,每个文件夹中都有一个index.js
文件(帖子、项目或页面的登录页(和一个使用新语法{type.field}.js
的模板文件 - 能够在各自的index.js文件中查询
allPosts
/allProjects
/allPages
,并将这些类型用于模板文件({Post.slug}.js
、{Project.slug}.js
等( - 模板文件将以与基本教程中使用
allMdx
和mdx
相同的方式查询子节点(post
、project
、page
( - 不需要使用
gatsby-node.js
中的createPages
挂钩,因为gatsby-source-filesystem
应该用上面的结构为我做这件事
我发现这篇stackoverflow帖子提出了一个类似的问题,但答案似乎意味着这些自定义节点(allPosts
等(应该在你设置这样的插件选项时自动创建:
{
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/content/posts`,
},
},
然而,这对我来说并不奏效。当我使用__graphql
接口时,这些节点不存在,如果我试图以任何方式查询它们,我会得到一个错误(注意:我曾尝试使用projects
、Project
、project
等命名模板文件,但没有成功(:
PageCreator: Tried to create pages from the collection builder.
Unfortunately, the query came back empty. There may be an error in your query:
Cannot query field "allProjects" on type "Query".
File: src/pages/projects/{projects.slug}.js
我还找到了这本盖茨比指南,它似乎解决了我的部分问题,但我不明白如何在本地获取数据,而不是通过他们使用的API请求。我还认为这可能会使一些非常简单的东西过于复杂,而这些东西本应与mdx和文件系统插件一起使用?不确定!
我觉得我错过了一些基本的东西。我还是盖茨比的新手,所以我完全有可能错了,认为这会按照我的意愿进行,但我花了几个小时试图弄清楚这一点,认为是时候最终寻求帮助了,哈哈。
任何建议都将不胜感激!!
您可以尝试这个Gatsby插件https://www.gatsbyjs.com/plugins/gatsby-plugin-mdx-source-name/?=mdx
我什么时候使用这个插件?如果您正在使用gatsby源文件系统的多个实例,则此插件非常有用,因为它将允许您从Mdx节点上的源插件中查询名称字段。
plugins: [
`gatsby-plugin-mdx-source-name` ,
{
resolve: `gatsby-source-filesystem` ,
options: {
path: `${__dirname}/src/blog` ,
name: `blog` // this name will be added to the Mdx nodes
}
}
]
源名称现在可以通过GraphQL:进行查询
const query = graphql`
query {
allMdx(){
nodes {
id
fields {
source
}
}
}
}`
例如,如果您想在页面创建时通过这个新的源字段进行筛选,您可以执行以下操作:
// gatsby-node.js
exports.createPages = ({actions, graphql}) => {
const {createPage} = actions
// query for all Mdx pages
const query = graphql(`
query {
allMdx(){
nodes {
fields {
source
}
frontmatter {
slug
}
}
}
}
`)
return query.then(result => {
// filter by source name "blog"
const posts = result.data.allMdx.nodes.filter(node => node.fields.source === 'blog')
posts.forEach(node => {
createPage({
path: `/blog/${node.frontmatter.slug}`,
component: path.resolve('src/templates/blog-post.js'),
context: {
slug: node.frontmatter.slug
}
})
})
})
}
使用onCreateNode 创建自己的自定义类型
https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/#onCreateNode
https://www.gatsbyjs.com/docs/reference/graphql-data-layer/schema-customization/
我的解决方案是使用fileAbsolutePath根据我的文件所在的文件夹来确定.mdx文件是页面还是帖子等。
if (node.internal.type == 'Mdx' && node.fileAbsolutePath.indexOf('pages') !== -1) {
actions.createNode({
id: createNodeId(`MdxPage-${node.id}`),
parent: node.id,
internal: {
type: `MdxPage${node.internal.type}`,
contentDigest: node.internal.contentDigest,
},
})
}
另一个选项是按照您所描述的进行文件夹结构,而不是使用allMdx基于fileAbsolutePath
:进行过滤
allMdx(
sort: { fields: frontmatter___date, order: DESC }
filter: { fileAbsolutePath: {regex: "/content/projects/"} }
)
或者,如果您希望在使用别名的同一查询中多次调用allMdx:
projects: allMdx(
filter: { fileAbsolutePath: {regex: "/content/posts/"} }
) { ... }
posts: allMdx(
filter: { fileAbsolutePath: {regex: "/content/projects/"} }
) { ... }