我正在用GatsbyJS建立一个网站。我在两个不同的文件夹中分别有markdown文件:/content/collections
和/content/posts
,我希望Gatsby为每个markdown文件创建一个页面,并带有各自的模板(collection.js和post.js)。
所以我在gatsby-node.js文件中写了这个:
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions;
if (node.internal.type === 'MarkdownRemark') {
const longSlug = createFilePath({ node, getNode, basePath: 'content' });
const slug = longSlug.split('/');
createNodeField({
node,
name: 'slug',
value: `/${slug[slug.length - 2]}/`,
});
}
};
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const result = await graphql(`
query {
allFile(filter: {relativeDirectory: {eq: "collections"}}) {
edges {
node {
childMarkdownRemark {
fields {
slug
}
}
}
}
}
}
`);
result.data.allFile.edges.forEach(({ node }) => {
createPage({
path: node.childMarkdownRemark.fields.slug,
component: path.resolve('./src/templates/collection.js'),
context: {
slug: node.childMarkdownRemark.fields.slug,
},
});
});
};
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const result = await graphql(`
query {
allFile(filter: {relativeDirectory: {eq: "posts"}}) {
edges {
node {
childMarkdownRemark {
fields {
slug
}
}
}
}
}
}
`);
result.data.allFile.edges.forEach(({ node }) => {
createPage({
path: node.childMarkdownRemark.fields.slug,
component: path.resolve('./src/templates/post.js'),
context: {
slug: node.childMarkdownRemark.fields.slug,
},
});
});
};
认为它将起作用。确实适用于我输入的第二种类型。(在这种情况下,它创建帖子,但不创建集合。如果我颠倒了调用createPages的顺序,它将交换,但它从不创建所有主题)
这是我在控制台中看到的错误:
warning The GraphQL query in the non-page component "/Users/matteocarpi/Documents/Web/Ledue/src/templates/collection.js" will not be run.
Exported queries are only executed for Page components. It's possible you're
trying to create pages in your gatsby-node.js and that's failing for some
reason.
If the failing component(s) is a regular component and not intended to be a page
component, you generally want to use a <StaticQuery> (https://gatsbyjs.org/docs/static-query)
instead of exporting a page query.
If you're more experienced with GraphQL, you can also export GraphQL
fragments from components and compose the fragments in the Page component
query and pass data down into the child component — https://graphql.org/learn/queries/#fragments
这两个模板非常相似:
import React from 'react';
import { graphql } from 'gatsby';
import PropTypes from 'prop-types';
const Post = ({data}) => {
return (
<div>
<h1>{data.postData.frontmatter.title}</h1>
</div>
);
};
export default Post;
export const query = graphql`
query PostData($slug: String!) {
postData: markdownRemark(fields: {slug: {eq: $slug}}) {
frontmatter {
title
}
}
}
`;
Post.propTypes = {
data: PropTypes.node,
};
import React from 'react';
import { graphql } from 'gatsby';
import PropTypes from 'prop-types';
const Collection = ({data}) => {
return (
<div>
<h1>{data.collectionData.frontmatter.title}</h1>
</div>
);
};
export default Collection;
export const query = graphql`
query CollectionData($slug: String!) {
collectionData: markdownRemark(fields: {slug: {eq: $slug}}) {
frontmatter {
title
}
}
}
`;
Collection.propTypes = {
data: PropTypes.node,
};
我尝试重构this answer之后的所有gatsby-node.js文件,但最终遇到了同样的情况。
我在哪里弄错了?
答案 0 :(得分:3)
问题在于您要用第二个覆盖第一个函数声明。像这样:
var a = "hello"
a = "world"
相反,您应该执行所有查询并为要在单个函数中创建的所有页面调用createPage
,如下所示:
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions;
const collections = graphql(`
query {
allFile(filter: {relativeDirectory: {eq: "collections"}}) {
edges {
node {
childMarkdownRemark {
fields {
slug
}
}
}
}
}
}
`).then(result => {
result.data.allFile.edges.forEach(({ node }) => {
createPage({
path: node.childMarkdownRemark.fields.slug,
component: path.resolve('./src/templates/collection.js'),
context: {
slug: node.childMarkdownRemark.fields.slug,
},
});
});
})
const posts = graphql(`
query {
allFile(filter: {relativeDirectory: {eq: "posts"}}) {
edges {
node {
childMarkdownRemark {
fields {
slug
}
}
}
}
}
}
`).then(result => {
result.data.allFile.edges.forEach(({ node }) => {
createPage({
path: node.childMarkdownRemark.fields.slug,
component: path.resolve('./src/templates/post.js'),
context: {
slug: node.childMarkdownRemark.fields.slug,
},
});
});
})
return Promise.all([collections, posts])
};