在盖茨比上创建第二个博客模板

时间:2019-10-16 22:27:19

标签: javascript node.js gatsby

我正在尝试在Gatsby网站上创建第二个博客模板。我只是开始学习Javascript,因此我需要gatsby-node.js文件的帮助。

我试图复制每行功能以本质上创建第二个博客模板,但是每次都失败,因此如果有人可以遍历我的代码并提供正确的功能,将非常有帮助。

我目前有一个“文章”模板,该模板可以成功运行。我要创建第二个“项目”模板。

这是我当前的gatsby-node.js文件,仅调用“文章”博客模板。


const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');

// Look at every node when it is created
exports.onCreateNode = ({node, getNode, actions}) => {
  // Check for markdown nodes
  const { createNodeField } = actions;
  if(node.internal.type === 'MarkdownRemark') {
    // Create a slug out of the markdown filepath name
    const slug = createFilePath({
      node,
      getNode,
      basePath: 'articles'
    });
    // Add the newly created slug to the node itself
    createNodeField({
      node,
      name: 'slug',
      value: `/article${slug}`
    });
  }
};

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return new Promise((resolve, reject) => {
    graphql(`
    {
      allMarkdownRemark {
      edges {
        node {
        fields {
          slug
        }
        }
      }
      }
    }
    `).then(result => {
    result.data.allMarkdownRemark.edges.forEach(({ node }) => {
      createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/article.js`),
      context: {
        // Data passed to context is available in page queries as GraphQL variables.
        slug: node.fields.slug,
      },
      })
    })
    resolve()
    })
  })
  };


如何配置此文件以调用第二个博客模板(“项目”)?

1 个答案:

答案 0 :(得分:2)

首先,您需要检索您的文章以及在graphql查询中获得的项目。您可以使用冒号重命名查询的一部分。我在您的allMarkdownRemark之前添加了articles:。在生成的JSON中,allMarkdownRemark现在将称为“文章”。您可以在forEach循环中看到这一点,该循环现在遍历“ result.data.articles”。我还为所需的“项目”实体添加了查询。将它们重命名为文章和项目,使我们可以轻松地遍历每篇文章和每个项目,并为这些实体创建正确的页面。

项目查询现在是文章查询的副本。实际上,您应该在此处提供仅返回项目的查询,但我不知道您在哪里。然后为您在其中创建正确页面的项目和文章创建单独的循环。

exports.createPages = ({ graphql, actions }) => {
    const { createPage } = actions

    return new Promise((resolve, reject) => {
        graphql(`{
            articles: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
            projects: allMarkdownRemark {
                edges {
                    node {
                        fields {
                            slug
                        }
                    }
                }
            }
        }`).then(result => {

            // In this loop we only take the articles returned by the query, and
            // pass them to the src/templates/article.js component.
            result.data.articles.edges.forEach(({ node }) => {
                createPage({
                    // Rather than prepending every slug with '/article' in the
                    // createNodeField call, you can add it here to get more
                    // flexibility, and to allow different types to have different
                    // path prefixes.
                    path: `article/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/article.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            // In this loop we do the same thing, only with the projects this
            // time, and passing them to the project.js component I'm assuming
            // you have. I've prepended the path with 'project/' to separate
            // the projects from the articles.
            result.data.projects.edges.forEach(({ node }) => {
                createPage({
                    path: `project/${node.fields.slug}`,
                    component: path.resolve(`./src/templates/project.js`),
                    context: {
                        slug: node.fields.slug,
                    },
                })
            })

            resolve()
        })
    })
};

我添加了一些缩进,以使事情更容易推理。我可能在此过程中犯了一些语法错误,所以请当心。

我注意到在您的onCreateNode调用中,您将每个降价文件的标签设置为'article / $ {slug}`。如果您的项目也是markdown文件,则不应这样做,因为它还会使您的项目markdown文件以“ / article”开头。在上面的代码中,我在createPage调用中设置了正确的路径,而不是在createNodeField中。

您需要牢记的一件事是,如果您既将文章和项目都作为降价文件获得,则查询将很难区分它们。我通常解决此问题的方法是在前题中添加“类型”字段。因此,在您的情况下,您将:type: article添加到所有文章的开头,type: project添加到所有项目。最重要的部分是markdown文件顶部的三个虚线之间的部分:

---
type: article
name: something
etc, etc...
---

您可以像这样过滤您的markdown文件:

graphql(`query {
      projects: allMarkdownRemark ( filter: {frontmatter: { type: { eq: "project" } } } ) {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }`);

这将仅返回具有project类型的markdown文件。对您的文章执行相同的操作。如果您使用Netlify CMS,则可以添加一个隐藏字段以自动添加正确的类型来帮助您进行过滤。

您可能要考虑将Promise更改为async / await调用。这是可选的,但我认为它使事情更容易阅读。在此处https://www.gatsbyjs.org/tutorial/part-seven/#creating-pages中查看gatsby的教程,以获取createPages API中异步/等待的示例。

相关问题