概述
在进行TypeScript应用程序开发之前,我们需要完成一个重要的步骤:我们需要为方案中的所有GraphQL类型生成 TypeScript类型!
在本课程中,我们将
- 配置GraphQL代码生成器
- 从我们的GraphQL API生成类型,这些类型可以在我们的前端代码中使用
生成类型
目前,我们的前端应用程序对我们的后端GraphQL API所使用的方案一无所知。但因为我们将要为Track
和Author
数据编写查询,我们需要让前端了解它们涉及的数据类型。我们可以手动编写TypeScript类型—— 我们知道,通过检查Sandbox中的方案参考,一个Track
有一个用于标题的文本,并有一个Author
有一个用于名字的文本,等等——但我们如果未来更改方案,我们必须记得更新我们的前端;这意味着如果我们的前端不谨慎,我们的前端TypeScript类型可能会很容易与方案脱节!
相反,我们可以将 GraphQL API 的架构视为前端所有可能 查询 类型“单一事实来源”。实现这一点并确保我们的前端类型定义与后端保持一致的一种简单方法是使用 GraphQL 代码生成器。
@graphql-codegen/cli
是这样的一个工具,它可以从 GraphQL架构 读取,将其与我们要求前端代码运行的操作进行对比,并生成前端所需的所有类型。在我们开发新功能时,我们将从 TypeScript 给我们的清晰性中受益,它让我们了解每种类型上存在哪些数据,以及可以对它执行哪些类型的 操作。
代码生成概述
以下是这个过程的工作原理。
- 首先,我们将安装我们的软件包,并设置一个
generate
命令以 启动 代码生成器。 - 接下来,我们将创建一个配置文件来指导代码生成过程。最基本的是,它指定了 GraphQL架构 的路径,它应检查我们前端应用程序中的文件以进行 GraphQL 操作,以及输出必要 TypeScript类型的路径。
- 我们将运行代码生成命令。
- 最后,我们将检查为我们生成的类型。
准备好开始了吗?我们走吧!
步骤 1:安装 @graphql-codegen/cli
让我们开始安装 GraphQL 代码生成器并在我们的项目中安装它。我们还将安装 GraphQL,它将为我们提供一些内置的 React 配置。
我们只需要在开发过程中使用这些包,所以我们将它们安装在 devDependencies
下。
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset
当安装完成时,打开 package.json
。在 scripts
键下,我们将添加一个新的命令,generate
,将调用 @graphql-codegen/cli
软件包。
"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
的文件。
// TODO
该文件应包含一些指令,告诉 GraphQL 代码生成器我们想要它做什么,例如:
- 我们的 GraphQL API 运行在哪里,以便它可以从 GraphQL API 中检索有关类型和表单中存在的字段的信息。
- 它应该检查哪些前端文件以找到我们使用的所有GraphQL 操作(目前我们没有任何操作!)
- 它应该将其生成的类型输出到何处。GraphQL 代码生成器将使用我们提供的所有信息,在选定的文件夹中输出生成的类型。
我们首先创建一个名为config
的新对象并将其导出。
const config = {};export default config;
接下来,让我们导入我们将用于config
对象的类型定义。@graphql-codegen/cli
为我们提供了一个内置的类型定义。
import { CodegenConfig } from "@graphql-codegen/cli";const config: CodegenConfig = {};export default config;
在config
对象中,我们将定义三个属性:schema
, documents
和generates
。
schema
属性
对于schema
属性,我们需要传递我们的GraphQL 服务器的端点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应用的良好协作,特别是那些使用Apollo Client的应用。它还提供了我们可以调整以改变代码生成器行为的附加插件。
我们将添加client
预设指示符到对象中,如下所示。
generates: {"./src/__generated__/": {preset: "client",},},
定制graphql
函数
我们想要控制生成的代码的另一部分是代码生成器将提供给我们用于查询的graphql
函数的名称。这个函数是一个带标记的模板字面量,我们使用它来为GraphQL字符串准备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
命令,我们会看到一个错误:这是因为当前我们的前端代码没有任何 GraphQL 操作供代码生成器扫描。
Unable to find any GraphQL type definitions for the following pointers:- src/**/*.tsx
不管怎样运行该命令,查看代码生成器默认为我们输出的内容,我们可以在我们的config
对象中传递一个额外的标志,该标志命名为ignoreNoDocuments
。通过将ignoreNoDocuments
设置为true
,我们告诉GraphQL代码生成器不需要担心它在我们前端代码中没有找到任何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:检查输出
让我们看看 GraphQL 代码生成器为我们创建的文件。
📂 __generated__┣ 📄 fragment-masking.ts┣ 📄 gql.ts┣ 📄 graphql.ts┗ 📄 index.ts
第一个文件 fragment-masking.ts
包含一些函数,这些函数将帮助我们处理 GraphQL fragments(关于这方面的更多信息可以在 Side Quest: Intermediate Schema Design)中找到。第二个文件, gql.ts
,包含我们要求的 gql
函数,该函数能够帮助解析 GraphQL 查询,以便可以被 GraphQL 客户端,如 Apollo Client。
然而,当我们进入 graphql.ts
时,我们会看到一些非常有趣的东西——在该文件的底部,我们可以找到我们在后端 schema 中定义的三种类型!
Query
,Track
,和 Author
已成功地从运行在 https://odyssey-lift-off-server.herokuapp.com/
的我们的 GraphQL 服务器中 introspected,并且 GraphQL 代码生成器已生成有关它们包含的字段和数据类型的所有信息!
虽然我们还没有在前端编写任何 GraphQL operations,但我们已看到 GraphQL 代码生成器如何拉取有关我们前端将处理的数据类型的信息。
从现在起,我们想了解是否有任何 GraphQL 文档供代码生成器扫描,这样我们就可以通过移除 ignoreNoDocuments
标志来清理我们的 codegen.ts
文件。(运行 npm run generate
仍然会产生错误,但我们在下一课中会通过添加第一个 GraphQL 操作来解决它!)
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[]' 类型” 的错误消息是指我们的生成代码(找不到任何要包含的 GraphQL 操作),我们将在下一课中解决这个问题!
关键要点
- 我们可以使用 GraphQL 代码生成器从模式中读取类型和字段,并生成相应的 TypeScript 类型。
- 我们使用
codegen.ts
文件来告诉 GraphQL 代码生成器我们的 GraphQL API 运行在哪里,我们希望在何处存储生成的类型以及要使用的插件。
接下来
就用不客气的话,我们来为我们的前端应用程序提供一个查询,并用数据填充主页!
分享您对这一课的疑问和评论
此课程目前处于
您需要 GitHub 账户才能发表以下评论。没有吗? 请在我们的大航海家论坛发表帖子。