引言
个人项目 《仿 Mac 个人网站开发 |项目复盘》 很早之前就用上了 Graphql
, 近期对前端项目整体做了升级(转 NextJS
、引入 react-query
)! 在翻代码时看到之前配置的 Graphql Codegen 然后就是一脸懵逼(时间太久了, 都忘记每项配置的作用了...), 所以就重新查阅了下官网, 对这一块配置也进行了升级, 整个流程又重新走了一遍! 故而就有了本篇文章!!
一、什么是 Graphql Codegen
首先 Graphql Codegen 是一个 开发/构建
工具
, 它主要的作用其实就是帮助我们自动生成 TS
类型
具体的来讲就是, 假设你的后端是 Graphql
服务, 并且在前端你是通过常规编写 Graphql
方式来调用接口的, 那么通过 Graphql Codegen 能够帮助你减少大量工作, 该工具可以监听 Graphql
操作, 并根据指定的 Graphql
服务, 生成所有必备的接口响应、请求参数等一些列 TS
类型, 甚至可以帮助你快速生成 useQuery
或 useMutation
等 hooks
!!
有了它可以大大减少您必须编写的样板代码, 使得使用 GraphQL API
变得更加容易, 便捷! 并且通过简单的配置, 可以让 TS
的发挥最大化(智能提示)
二、配置讲解
其实官方已经提供了很 详细的文档, 本文只是做了些适当的简化、和说明, 所以在整个过程中, 如果遇到任何问题, 请以 官方 为准!!!!
2.1 基础配置
- 安装
@graphql-codegen/cli
依赖: 提供生成代码所必要的一些CLI
工具
sh
pnpm add --save-dev @graphql-codegen/cli
- 项目
根目录
下创建配置文件codegen.ts
ts
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "http://localhost:4000/api/graphql",
documents: ["src/**/*.tsx"],
ignoreNoDocuments: true,
generates: {
"./src/graphql/": {
preset: "client",
config: {
documentMode: "string",
},
},
},
};
export default config;
配置项说明:
schema: xxxx
用于指定后端Graphql
服务地址, 我这边后端服务
地址为http://localhost:4000/api/graphql
documents
指定当前前端
项目中可能包含Graphql
操作的文件, 这个文件中如果匹配到Graphql
操作代码, 则会自动生成我们预期的TS
类型代码generates
定义要生成的内容, 该配置是一个对象, 对象的key
是生成内容文件对应的路径(可以是具体的文件、也可以是个目录), 而值则是生成的配置项(规定如果生成代码、生成怎么样的代码), 这里的配置和Babel
有点像, 都是可以指定preset
、plugins
等内容- 更多配置内容参考: docs/config-reference/codegen-config
2.2 测试效果
是的没错, Graphql Codegen 配置很简单, 就简单的两步即可, 下面我们来看下它的效果(作用)!
- 随便找个地方, 写个页面(我这里是
NextJS
项目)
ts
"use client";
const Demo = () => {
return <div>11111</div>;
};
export default Demo;
- 下面问题来了, Graphql Codegen 是如何识别出文件中包含的
Graphql
操作代码呢? 其实就是通过一些特定的标识、写法、文件名, 来识别的。下面是我所知道的几种写法
- 调用函数
graphql
或gql
, 其参数字符串
会被视为Graphql
操作代码, 即便函数没有定义(因为并没执行代码, 无所谓有没定义)
ts
// graphql 函数的字符串参数会被视为 Graphql 操作代码, 被识别到
const getUserInfo = graphql(`
query getUserInfo {
userInfo {
user {
id
name
}
message
}
}
`);
// gql 函数的字符串参数会被视为 Graphql 操作代码, 被识别到
const getUserInfo = gql(`
query getUserInfo {
userInfo {
user {
id
name
}
message
}
}
`);
- 通过注释
/* GraphQL */
将一串字符串标记为Graphql
操作代码
js
// 注释 /* GraphQL */ 后面字符串, 会被视为 Graphql 操作代码, 被识别到
const gql = /* GraphQL */ `
query getUserInfo {
userInfo {
user {
id
name
}
message
}
}
`;
- 特定文件: 对于所有以
.gql
或.graphql
作为后缀名的, 文件内容会被视为Graphql
操作代码, 被识别到
gql
query getUserInfo {
userInfo {
user {
id
name
}
message
}
}
这里需要注意的是: 上面
codegen.ts
配置中documents
并没有包含.gql
或.graphql
文件, 这里如果要测试, 记得补充上!!!
- 触发生成: 通过执行
raphql-codegen --config codegen.ts
命令, 可触发代码生成, 如下:
sh
npx graphql-codegen --config codegen.ts
执行命令后将生成相应的代码
graphql/fragment-masking.ts
: 使用Graphql
片段所需要用到的TS
以及hooks
graphql/gql.ts
: 代码中的所有Graphql
操作对应documents
, 同时还导出了一个方法, 用于获取对应Graphql document
graphql/graphql.ts
: 根据后端Graphql
服务生成的, 接口数据类型、参数graphql/index.ts
: 入口文件, 导出所有用到的方法
2.3 使用: 如何发起一个请求
下面我们就可以使用 @tanstack/react-query
和 graphql-request
来简单演示下如何使用 Graphql Codegen 生成的产物来发起一个简单的请求!
如下代码所示:
- 直接在文件顶部编写
Graphql
操作- 通过
graphql-request
发送Graphql
请求, 需要注意的是新版本的graphql-request
不再支持相对路径, 具体可以看这篇Issues
Support passing relative path for URL #745
ts
"use client";
import { graphql } from "@/graphql";
import request from "graphql-request";
import { useQuery } from "@tanstack/react-query";
// 1. 编写 Graphql 操作
const getUserInfoDocument = graphql(`
query getUserInfo {
userInfo {
user {
id
name
}
message
}
}
`);
const Demo = () => {
// 2. 请求接口
const { data } = useQuery({
queryKey: ["getUserInfo"],
queryFn: async () => request("http://localhost:3000/api/graphql", getUserInfoDocument),
});
console.log(data);
return <div>11</div>;
};
export default Demo;
开始前, 我们先执行 raphql-codegen --config codegen.ts
命令, 生成相关代码
sh
npx graphql-codegen --config codegen.ts
最后启动项目, 并访问 DEMO
页面, 不出意外的话, 在控制台应该是可以看到预期的结果
2.4 简单请求函数封装
上文我们是直接调用 graphql-request
来发起请求的, 然而在实际项目中! 肯定不能这么整, 我们还是需要简单封装一个工具函数, 最些简单的封装, 目的其实就是为了处理一些个性化配置, 比如请求路径处理、请求头处理、参数处理、响应错误处理.....
如下所以, graphql-request
允许我们创建一个自己的实例, 在创建实例时我们就可以进行一些简单的配置
js
import { GraphQLClient, ClientError } from "graphql-request";
import { createApi, BaseQueryFn } from "@reduxjs/toolkit/query/react";
// see: https://github.com/prisma-labs/graphql-request
const client = new GraphQLClient("http://localhost:3000/api/graphql", {
mode: "cors",
credentials: "include",
});
export default client;
调用方式也简单, 只需要调用 client.request
即可, 正如下文你所看到的, 一切都变得更加简单...
ts
const { data } = useQuery({
queryKey: ["getUserInfo"],
queryFn: async () => client.request(getUserInfoDocument),
});
三、集成 VSCode
既然, 我们能够生成所有 Graphql
服务的相关 TS
配置, 那么自然要发挥其最大的作用!!! 我们希望在编写 Graphql
操作片段时, 能够提供完备的智能提示!
3.1 生成「GraphQL」服务模型
首先我们需要一份 GraphQL
后端服务的完整模型架构, 这里我们一样可以直接通过 Graphql Codegen 来帮助我们快速生成!
这里我们需要先通过 @graphql-codegen/schema-ast
插件来生成 GraphQL
后端服务的完整模型架构!! 下面我们来安装下 @graphql-codegen/schema-ast
sh
pnpm add @graphql-codegen/schema-ast -D
接下来修改 codegen.ts
配置文件: 使用 @graphql-codegen/schema-ast
插件, 输出 GraphQL
服务模型到 schema.graphql
文件中
diff
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: "http://localhost:4000/api/graphql",
documents: ["src/**/*.tsx"],
ignoreNoDocuments: true,
generates: {
"./src/graphql/": {
preset: "client",
},
+ "./schema.graphql": {
+ plugins: ["schema-ast"],
+ config: {
+ includeDirectives: true,
+ },
},
},
};
export default config;
最后执行 npx graphql-codegen --config codegen.ts
sh
npx graphql-codegen --config codegen.ts
最终会在项目根目录下创建预期的文件:
3.2 VSCode 配置
到目前我们只是生产了一份 GraphQL
服务模型, 但并没有将其运用起来, 下面我们需要做的就是借助 @0no-co/graphqlsp
来帮助我们更好的编写代码
- 安装依赖包
@0no-co/graphqlsp
sh
pnpm add @0no-co/graphqlsp -D
- 修改
tsconfig.json
配置: 使用@0no-co/graphqlsp
diff
{
"compilerOptions": {
....
"plugins": [
+ {
+ "name": "@0no-co/graphqlsp",
+ "schema": "./schema.graphql"
+ }
],
},
...
}
- 修改
.vscode/settings.json
diff
{
....
+ "typescript.tsdk": "node_modules/typescript/lib",
+ "typescript.enablePromptUseWorkspaceTsdk": true
}
3.3 测试效果
到此本小节配置结束, 下面看下效果吧!
- 编写过程中, 会给出所有可选内容
- 对于不存在的字段, 会给出提示和建议
- ...
四、更多优化配置
到处本文的目的基本完成, 后面则是一些个人的一些配置上的优化!
4.1「Npm」脚本配置
为命令 npx graphql-codegen --config codegen.ts
配置一条 Npm
脚本, 毕竟每次手打也很麻烦!!!
所以这里我就增加有一条 Npm
脚本, 如下所示调整 package.json
diff
{
"name": "klx-website",
...
"scripts": {
"dev": "next dev",
"cz": "klx-cz",
"release": "klx-release",
"prepare": "husky install",
+ "gql-codegen": "graphql-codegen --config codegen.ts"
},
}
后面如需手动执行 Graphql Codegen 只需要执行:
sh
npm run gql-codegen
4.2 开启监听模式
每次修改完 GraphQL
操作代码, 总是要手动执行 Graphql Codegen CLI
命令肯定是不靠谱的!
更好的体验肯定是只要我们修改了 GraphQL
操作代码, 在保存内容后, 能够自动执行 Graphql Codegen CLI
完成代码的生成!!
要做到这一步, 我们还需要借助 @parcel/watcher
工具! 所以我们先把该依赖包下载下来!
sh
pnpm add @parcel/watcher -D
接下来我们就可以为 graphql-codegen
命令添加 --watch
参数, 开启监听模式, 如此只要 GraphQL
操作代码发生修改, 就会触发 graphql-codegen
命令, 生成新的代码!
最后调整下 package.json
种的 Npm
脚本: 希望在执行 dev
脚本(跑项目)的同时, 能够开启 graphql-codegen
diff
{
"name": "klx-website",
...
"scripts": {
+ "dev": "next dev & npm run gql-codegen -- --watch",
"cz": "klx-cz",
"release": "klx-release",
"prepare": "husky install",
+ "gql-codegen": "graphql-codegen --config codegen.ts"
},
}