使用graphql codegen生成hooks的方法以及遇到的一些困难
困境的经过
作为GraphQL的练习,我尝试在前端使用codegen自动生成代码。
因为之前也使用过,所以在设置方面并不太困难,但这次我想要自动生成hooks,所以改变了设置内容。
关于实现的概述将在下一章中进行解释。
以下是出现问题的错误:
名称 `GetUsersDocument` 被多次定义。
执行
安装 codegen
安装依赖:
“`
pnpm i -D graphql @graphql-codegen/cli
“`
初始化 codegen
pnpm grapql-codegen init
在对话形式下开始初始化(本例中选择使用React作为Next.js项目)。
? What type of application are you building? (Use arrow keys)
Backend - API or server
Application built with Angular
❯ Application built with React
Application built with Stencil
Application built with Vue
Application using graphql-request
Application built with other framework or vanilla JS
本次架构的位置指定为本地主机的8080端口上启动的graphql服务器。
? Where is your schema?: (path or url) http://localhost:8080/v1/graphql
指定读取GraphQL文档的路径。
? Where are your operations and fragments?:src/graphql/**/*.graphql
设定生成的代码输出到哪里(这次是src/generates/)。
? Where to write the output: src/generates/
这次是否要创建内省文件?(是的)
? Do you want to generate an introspection file? (y/N)
配置文件的名称(此处为默认值)
? How to name the config file? (codegen.ts)
npm命令名称(这也是默认值)
? What script in package.json should run the codegen? (codegen)
对话结束。
Fetching latest versions of selected plugins...
Config file generated at codegen.ts
$ npm install
To install the plugins.
$ npm run codegen
To run GraphQL Code Generator.
因为有人告诉我要执行”npm install”,所以我执行了”pnpm install”。
试着创建查询文档
query GetUsers {
users {
id
userName
}
}
在数据库中,有一个名为”users”的表,该表包含了”id”和”userName”两个列。
当你执行 codegen 的时候,因为有人告诉你要用 npm run codegen,所以你可以执行 pnpm codegen。
结构如下所示
src
├── generates
│ ├── fragment-masking.ts
│ ├── gql.ts
│ ├── graphql.ts
│ └── index.ts
├── graphql
│ └── query
│ └── getUser.graphql
到此为止,简单的GraphQL代码生成已完成。
本题
本次目标是生成hooks。
安装必要的库
npm i -D @graphql-codegen/typescript @graphql-codegen/typescript-react-apollo @graphql-codegen/typescript-operations @apollo/client
将 codegen.ts 进行以下修改:
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: "http://localhost:8080/v1/graphql",
documents: "src/graphql/**/*.graphql",
generates: {
"src/generates/": {
preset: "client",
plugins: [
"typescript",
"typescript-operations",
"typescript-react-apollo",
],
config: {
skipTypename: false,
withHOC: true,
withComponent: false,
scalars: {
uniqueidentifier: "string",
},
},
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
};
export default config;
设定用于plugins使用的插件
可以通过配置来设置生成的代码的详细信息。
实际执行查询时,略去了一些内容,结果输出以下错误信息。
./src/generates/graphql.ts
NonErrorEmittedError: (Emitted value instead of an instance of Error)
x the name `GetUsersDocument` is defined multiple times
在graphql.ts文件中,错误的内容是声明了多个GetUserDocument。
当将 codegen.ts 文件按以下方式进行编辑后,错误问题得到了改善。
generates: {
"src/generates/graphql.ts": { //出力先の変更
//presetを削除
plugins: [
"typescript",
"typescript-operations",
"typescript-react-apollo",
],
config: {
skipTypename: false,
withHOC: false,
withComponent: false,//出力するファイルを一つに設定する
scalars: {
uniqueidentifier: "string",
},
},
},
"./graphql.schema.json": {
plugins: ["introspection"],
},
},
看起来是preset:”client”出了问题
「首先,什么是预设(preset)?」
根据公式文档,生成.preset是用于输出的预设列表。预设是根据输入模式动态创建输出文件列表的一种方式。near-operation-file-preset是一个很好的示例。
生成的代碼與預設生成的代碼是否重複導致輸出錯誤的感覺呢(由於對該領域的理解不夠,無法表達出太多觀點)。
输出hooks的好处
为什么这次选择将输出点设置为hooks?
如果不选择withHooks:true并且默认使用的话,获取数据的查询需要写成以下方式(由于本文主要涉及codegen,因此不作关于apollo client的解释)。
const getUsersDoc = gql`
query GetUsers {
users {
id
userName
}
}
`
const {data} = useQuery(getUserDoc)
然而,一旦应用设置,
query GetUsers {
users {
id
userName
}
}
const { data } = useGetUsersQuery();
我觉得将查询和函数分开存放到不同的文件中,并且函数命名基于文档,使得直观易懂。
如果不考虑hooks输出,可以将文档分成不同的文件。
对于个人来说,函数名称的改变更容易理解和适应。
如果说通过查看文档名称就能够理解这一点,那也许确实如此。
如果还有其他不同的意见,请告诉我,我会非常感激。
请提供更多上下文信息。