5. Codegen
10m

概述

在进行TypeScript应用程序开发之前,我们需要完成一个重要的步骤:我们需要为方案中的所有GraphQL类型生成 TypeScript类型

在本课程中,我们将

  • 配置代码生成器
  • 从我们的 API生成类型,这些类型可以在我们的前端代码中使用

生成类型

目前,我们的前端应用程序对我们的后端 API所使用的方案一无所知。但因为我们将要为TrackAuthor数据编写查询,我们需要让前端了解它们涉及的数据类型。我们可以手动编写TypeScript类型—— 我们知道,通过检查Sandbox中的方案参考,一个Track有一个用于标题的文本,并有一个Author有一个用于名字的文本,等等——但我们如果未来更改方案,我们必须记得更新我们的前端;这意味着如果我们的前端不谨慎,我们的前端TypeScript类型可能会很容易与方案脱节!

相反,我们可以将 API 的架构视为前端所有可能 类型“单一事实来源”。实现这一点并确保我们的前端类型定义与后端保持一致的一种简单方法是使用 代码生成器。

@graphql-codegen/cli 是这样的一个工具,它可以从 读取,将其与我们要求前端代码运行的操作进行对比,并生成前端所需的所有类型。在我们开发新功能时,我们将从 TypeScript 给我们的清晰性中受益,它让我们了解每种类型上存在哪些数据,以及可以对它执行哪些类型的

代码生成概述

以下是这个过程的工作原理。

  1. 首先,我们将安装我们的软件包,并设置一个 generate 命令以 代码生成器。
  2. 接下来,我们将创建一个配置文件来指导代码生成过程。最基本的是,它指定了 的路径,它应检查我们前端应用程序中的文件以进行 GraphQL ,以及输出必要 TypeScript类型的路径。
  3. 我们将运行代码生成命令。
  4. 最后,我们将检查为我们生成的类型。

准备好开始了吗?我们走吧!

步骤 1:安装 @graphql-codegen/cli

让我们开始安装 GraphQL 代码生成器并在我们的项目中安装它。我们还将安装 ,它将为我们提供一些内置的 React 配置。

我们只需要在开发过程中使用这些包,所以我们将它们安装在 devDependencies 下。

npm install -D @graphql-codegen/cli @graphql-codegen/client-preset

当安装完成时,打开 package.json。在 scripts 键下,我们将添加一个新的命令,generate,将调用 @graphql-codegen/cli 软件包。

package.json
"scripts": {
"test": "vitest",
"start": "vite",
"build": "vite build",
"generate": "graphql-codegen"
},

如果我们现在立即运行命令,比如使用 npm run generate,我们将看到一个错误——这是因为我们还没有创建代码生成器查看的 codegen.ts 文件。

Error: Unable to find Codegen config file!
Please make sure that you have a configuration file under the current directory!

步骤 2:定义配置文件

让我们在我们的项目根目录中定义一个名为codegen.ts的文件。

codegen.ts
// TODO

该文件应包含一些指令,告诉 GraphQL 代码生成器我们想要它做什么,例如:

  1. 我们的 GraphQL API 运行在哪里,以便它可以从 GraphQL API 中检索有关类型和表单中存在的的信息。
  2. 它应该检查哪些前端文件以找到我们使用的所有 操作(目前我们没有任何操作!)
  3. 它应该将其生成的类型输出到何处。GraphQL 代码生成器将使用我们提供的所有信息,在选定的文件夹中输出生成的类型。

我们首先创建一个名为config的新对象并将其导出。

codegen.ts
const config = {};
export default config;

接下来,让我们导入我们将用于config对象的类型定义。@graphql-codegen/cli为我们提供了一个内置的类型定义。

import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {};
export default config;

config对象中,我们将定义三个属性:schema, documentsgenerates

schema属性

对于schema属性,我们需要传递我们的的端点https://odyssey-lift-off-server.herokuapp.com/。GraphQL 代码生成器将查看此地址并读取服务器模式的类型和

const config: CodegenConfig = {
schema: "https://odyssey-lift-off-server.herokuapp.com/",
};

documents属性

>GraphQL 代码生成器在生成前端类型时应考虑的所有代码都包含在src文件夹中,并且我们想要确保它在所有src子文件夹中查找文件!最后,我们应该在配置中设置我们想要扫描的文件仅以.tsx结尾。

const config: CodegenConfig = {
schema: "https://odyssey-lift-off-server.herokuapp.com/",
documents: ["src/**/*.tsx"],
};

generates属性

最后,代码生成器需要知道的是,在哪里输出它生成的所有代码。where为了这个目的,我们将要求它在src下创建一个名为__generated__的新文件夹。我们将此设置为键,其值为包含一些其他配置的对象。

const config: CodegenConfig = {
schema: "https://odyssey-lift-off-server.herokuapp.com/",
documents: ["src/**/*.tsx"],
generates: {
"./src/__generated__/": {
// TODO
},
},
};

在这里,我们可以使用之前安装过的@graphql-codegen/client-preset包。这个包配置了代码生成器与React应用的良好协作,特别是那些使用的应用。它还提供了我们可以调整以改变代码生成器行为的附加插件。

我们将添加client预设指示符到对象中,如下所示。

generates: {
"./src/__generated__/": {
preset: "client",
},
},

定制graphql函数

我们想要控制生成的代码的另一部分是代码生成器将提供给我们用于查询的graphql函数的名称。这个函数是一个带标记的模板字面量,我们使用它来为字符串准备服务器。

当由代码生成器生成时,这个实用程序包含了代码生成器生成的所有类型的理解——这意味着我们不需要自己输入类型!我们可以简单地使用生成的函数,它会为我们做所有工作,查找我们传递给它的GraphQL

默认情况下,代码生成器以graphql导出此函数,但我们可以选择重命名它。我们可以通过在preset下设置一个额外的属性presetConfig来这样做。我们将使用名称gql

generates: {
"./src/__generated__/": {
preset: "client",
presetConfig: {
// TODO
},
},
},

这是一个对象,我们可以设置一个gqlTagName属性,以及我们为此函数所喜欢的名称gql

generates: {
"./src/__generated__/": {
preset: "client",
presetConfig: {
gqlTagName: "gql",
},
},
},

第3步:运行GraphQL代码生成器

如果我们现在运行npm run generate命令,我们会看到一个错误:这是因为当前我们的前端代码没有任何 供代码生成器扫描。

Unable to find any GraphQL type definitions for the following pointers:
- src/**/*.tsx

不管怎样运行该命令,查看代码生成器默认为我们输出的内容,我们可以在我们的config对象中传递一个额外的标志,该标志命名为ignoreNoDocuments。通过将ignoreNoDocuments设置为true,我们告诉代码生成器不需要担心它在我们前端代码中没有找到任何GraphQL操作;它仍然应该继续输出默认生成的代码。这将给我们一个机会看一下它还为我们生成了什么!

ignoreNoDocuments: true 添加到您的 config 对象中,如下所示:

import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "https://odyssey-lift-off-server.herokuapp.com/",
documents: ["src/**/*.tsx"],
generates: {
"./src/__generated__/": {
preset: "client",
presetConfig: {
gqlTagName: "gql",
},
},
},
ignoreNoDocuments: true,
};
export default config;

请在根目录下再次运行我们的生成命令。

npm run generate

如果一切顺利,我们将在终端看到一些绿色的勾号,并在 src 目录下看到一个名为 __generated__ 的新文件夹!

步骤 4:检查输出

让我们看看 代码生成器为我们创建的文件。

📂 __generated__
┣ 📄 fragment-masking.ts
┣ 📄 gql.ts
┣ 📄 graphql.ts
┗ 📄 index.ts

第一个文件 fragment-masking.ts 包含一些函数,这些函数将帮助我们处理 (关于这方面的更多信息可以在 Side Quest: Intermediate Schema Design)中找到。第二个文件, gql.ts,包含我们要求的 gql 函数,该函数能够帮助解析 GraphQL 查询,以便可以被 客户端,如

然而,当我们进入 graphql.ts 时,我们会看到一些非常有趣的东西——在该文件的底部,我们可以找到我们在后端 schema 中定义的三种类型!

QueryTrack,和 Author 已成功地从运行在 https://odyssey-lift-off-server.herokuapp.com/ 的我们的 服务器中 introspected,并且 代码生成器已生成有关它们包含的字段和数据类型的所有信息!

虽然我们还没有在前端编写任何 ,但我们已看到 代码生成器如何拉取有关我们前端将处理的数据类型的信息。

从现在起,我们想了解是否有任何 文档供代码生成器扫描,这样我们就可以通过移除 ignoreNoDocuments 标志来清理我们的 codegen.ts 文件。(运行 npm run generate 仍然会产生错误,但我们在下一课中会通过添加第一个 操作来解决它!)

import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "https://odyssey-lift-off-server.herokuapp.com/",
documents: ["src/**/*.tsx"],
generates: {
"./src/__generated__/": {
preset: "client",
presetConfig: {
gqlTagName: "gql",
},
},
},
- ignoreNoDocuments: true,
};
export default config;

我们已经准备好开始发送查询了!

注意:在这个阶段,您可能会看到客户端应用程序在 https://127.0.0.1:3000 上运行时出现的错误!关于 “变量 'documents' 隐式具有 'any[]' 类型” 的错误消息是指我们的生成代码(找不到任何要包含的 操作),我们将在下一课中解决这个问题!

关键要点

  • 我们可以使用 代码生成器从模式中读取类型和字段,并生成相应的 TypeScript 类型。
  • 我们使用 codegen.ts 文件来告诉 代码生成器我们的 GraphQL API 运行在哪里,我们希望在何处存储生成的类型以及要使用的插件。

接下来

就用不客气的话,我们来为我们的前端应用程序提供一个查询,并用数据填充主页!

上一页

分享您对这一课的疑问和评论

此课程目前处于

beta
.您的反馈帮助我们改进!如果您遇到困难或感到困惑,请告诉我们,我们将帮助您解决。所有评论都是公开的,必须遵守 Apollo 行为准则。注意,解决或处理过的评论可能会被删除。

您需要 GitHub 账户才能发表以下评论。没有吗? 请在我们的大航海家论坛发表帖子。