GraphQL:覆盖 slug

GraphQL: Overriding slugs

我正在用 Gatsby 开始我的第一个项目并且 运行 遇到了查询数据的问题 "may" 并不总是存在。这是我的 gatsby-node.js 文件:

const path = require('path');
const _ = require('lodash');

// Lifecycle methods

function attachFieldsToBlogPost({ node, actions }) {
  if (node.internal.type !== 'MarkdownRemark') {
    return;
  }

  const { createNodeField } = actions;

  const { slug, title } = node.frontmatter;
  const postPath = slug || _.kebabCase(title);

  createNodeField({
    node,
    name: 'slug',
    getter: node => node.frontmatter.slug, // eslint-disable-line no-shadow
    value: postPath,
  });

  createNodeField({
    node,
    name: 'url',
    value: postPath,
  });
}

exports.onCreateNode = function() { // eslint-disable-line func-names
  return Promise.all([attachFieldsToBlogPost].map(fn => fn.apply(this, arguments))); // eslint-disable-line prefer-rest-params
};

// Implementations

function getMarkdownQuery({ regex } = {}) {
  return `
    {
      allMarkdownRemark(
        sort: { fields: [frontmatter___date], order: DESC }
        filter: { fileAbsolutePath: { regex: "${regex}" } }
      ) {
        totalCount
        edges {
          node {
            fileAbsolutePath
            excerpt(pruneLength: 280)
            timeToRead
            frontmatter {
              title
              date
              slug
            }
            fields {
              url
              slug
            }
          }
        }
      }
    }
  `;
}

function createBlogPostPages({ edges, createPage }) {
  const component = path.resolve('src/templates/Post.js');

  edges.forEach(({ node }) => {
    const { slug, title } = node.frontmatter;
    const postPath = slug || _.kebabCase(title);

    createPage({
      path: postPath,
      component,
      context: {
        slug: postPath,
      },
    });
  });
}

exports.createPages = async({ actions, graphql }) => {
  const results = await Promise.all([
    graphql(getMarkdownQuery({ regex: '/src/posts/' })),
  ]);

  const error = results.filter(r => r.errors);
  if (error.length) {
    return Promise.reject(error[0].errors);
  }

  const [blogPostResults] = results;

  const { createPage } = actions;
  const blogPostEdges = blogPostResults.data.allMarkdownRemark.edges;

  createBlogPostPages({
    createPage,
    edges: blogPostEdges,
  });
};

而我的示例博客post内容是:

---
title: 'Hello world there'
date: '2018-08-25'
---

Here is some content.

```javascript
console.log('test')
```

当我提供 slug frontmatter 组件时,页面会按预期创建。但是,我只想在 slug 参数可用时使用它(因此检查 frontmatter 在 attachFieldsToBlogPostcreateBlogPostPages 中是否可用)。如果我删除 slug frontmatter 项,我会收到以下错误:

GraphQLError: Cannot query field "slug" on type "frontmatter".

有没有办法覆盖用于创建 post 页面的路径 "if" slug frontmatter 在那里?

希望这不会太模糊,因为这是我的第一个 Gatsby 项目,但似乎是一个非常有用的功能。谢谢!

如果您删除所有 slug 的情况,那么该字段将不再存在于 Gatsby 的内部架构中。您可能 运行 the issue described here.

只要您有至少 1 个带有 slug 字段的 markdown 文件,那么它就会存在于 Gatsby 的自动化 GraphQL 模式中,然后您的条件逻辑应该可以工作。