让我们来实践华丽的Gatsby.js,尝试改变数据类型

定制GraphQL模式

最近,我在尝试使用GraphQL来管理Markdown文件中的img时,遇到了类型推断错误,需要修改GraphQL的模式。因此,我需要学习这个指南!由于我的意译偏激,请谅解?‍♂️

需要基本了解GraphQL的模式语言

在这之前,其实我不知道GraphQL的写法,所以我会大致学习一下。我在上面链接的文章中进行了学习!

特别需要掌握的知识是有关于模式语言(用于定义Web API规范的)中的字段定义方法和接口的知识。

type Query {
 currentUser: User!
}
interface Node {
 id: ID!
}

接口是一个抽象的类型,它捆绑了一组必需的字段。

公式指南

我会查看官方指南。

这个指南

    • プラグインの作成者

 

    • 自動型類推によって作成されたスキーマを修正したい方(私)

 

    • ビルドの最適化を測る方

 

    スキーマに興味のある方

看起来是针对…的。虽然这里很长,但我们只处理前一部分。
如果你对此感兴趣,读下去可能会有好处!

GraphQL的优势在于可以同时处理多个信息源!为了实现这一点,必须生成GraphQL模式。

Markdown和JSON的例子

从Markdown文件生成博客文章,并使用JSON格式提供作者信息。有时候,某些撰稿人的信息会单独保存为另一个JSON文件。

---
title: Sample Post
publishedAt: 2019-04-01
author: jane@example.com
tags:
  - wow
---
# Heading
Text
[
  {
    "name": "Doe",
    "firstName": "Jane",
    "email": "jane@example.com",
    "joinedAt": "2018-01-01"
  }
]
[
  {
    "name": "Doe",
    "firstName": "Zoe",
    "email": "zoe@example.com",
    "receivedSwag": true
  }
]

为了使用GraphQL查询这些内容,我们需要使用gatsby-source-filesystem、gatsby-transformer-remark和gatsby-transformer-json插件。这些插件的内部操作是将markdown文件转换为具有唯一id和MarkdownRemark类型的节点对象。

作者数据被转换为 AuthorJson 类型的节点对象,贡献者数据被转换为 ContributorJson 类型的节点对象。

スクリーンショット 2020-05-18 18.57.49.png

节点接口

以下是由 Source 插件和 Transformer 插件创建的 Gatsby 的 GraphQL 模式。
它包括了 Id、parent、children 这些字段,还有 internal 类型字段。

interface Node {
  id: ID!
  parent: Node!
  children: [Node!]!
  internal: Internal!
}

type Internal {
  type: String!
}

** TODO: internal是什么?即使我查了也不是很清楚。

请提供一个例子,命名为autor.json。

Gatsby-transformer-json用于创建autor.json的节点类型的示例如下所示。

type AuthorJson implements Node {
  id: ID!
  parent: Node!
  children: [Node!]!
  internal: Internal!
  name: String
  firstName: String
  email: String
  joinedAt: Date
}

要查看Gatsby所创建的模式实际上,GraphQL Playground是一个推荐的选择。

在项目中

$ GATSBY_GRAPHQL_IDE=playground gatsby develop
スクリーンショット 2020-05-18 18.03.52.png

比我想象中更加紧密。

自动推理

让我们来看一下之前的author.json文件。

[
  {
    "name": "Doe",
    "firstName": "Jane",
    "email": "jane@example.com",
    "joinedAt": "2018-01-01"
  }
]

尽管没有进行任何类型定义,但GraphQL可以很好地运行。这是因为它可以进行类型推断。通过检查每个字段的内容并检查类型来实现。

然而,这种类型推断有两个问题点。

    • 時間がかかり、負担がかかる

 

    型とデータが異なっていた場合、型の類推が失敗する

关于第二点,我会举例说明。

  +  {
  +    "name": "Doe",
  +    "firstName": "John",
  +    "email": "john@example.com",
  +    "joinedAt": "201-04-02"
  +  }
  ]

加入部分存在拼写错误,导致无法解释为”日期”。

为了解决这些问题,需要明确指示类型。

类型定义

使用createType action可以明确地定义类型。

  exports.createSchemaCustomization = ({ actions }) => {
    const { createTypes } = actions
    const typeDefs = `
      type AuthorJson implements Node {
        joinedAt: Date
      }
    `
    createTypes(typeDefs)
  }

请注意不需要定义所有类型(如name、firstName等)的点。

有些人可能会坚持不进行类型推断!通过这样做可以提高性能。正如之前提到的,由于类型推断的负担很大,所以在大型项目中性能下降明显。可以使用@dontInfer指令来选择性地取消类型推断。

对于不清楚什么是指令的人,请看一下之前关于GraphQL架构的解释:https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type AuthorJson implements Node @dontInfer {
      name: String!
      firstName: String!
      email: String!
      joinedAt: Date
    }
  `
  createTypes(typeDefs)
}

这是以节制版本进行的。
关于Node接口提供的字段,不需要明确指定,因为Gatsby会帮忙添加。(如id、parent等)

嵌套类型

在过去,我们只处理了标量类型,例如 String 类型和 Date 类型。在 GraphQL 中,还有其他类型可供处理。

    • ID型

 

    • Int型

 

    • Float型

 

    • Boolean型

 

    JSON型

也可以处理诸如此类的内容。而且,还可以处理复杂的对象值。

让我们以markdown-remark为例。

根据以下描述,frontmatter.tags将始终是一个字符串数组。

  exports.createSchemaCustomization = ({ actions }) => {
    const { createTypes } = actions
    const typeDefs = `
      type MarkdownRemark implements Node {
        frontmatter: Frontmatter
      }
      type Frontmatter {
        tags: [String!]!
      }
    `
    createTypes(typeDefs)
  }

如果直接指定Frontmatter类型,则会失败,就像上述描述的那样。

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    # これは失敗!!!
    type Frontmatter {
      tags: [String]!
    }
  `
  createTypes(typeDefs)
}

因为Frontmatter类型由源插件或转换插件创建,因此Node接口无法实现。

为了这个原因,会进行这样的处理。

广告
将在 10 秒后关闭
bannerAds