使用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输出,可以将文档分成不同的文件。
对于个人来说,函数名称的改变更容易理解和适应。
如果说通过查看文档名称就能够理解这一点,那也许确实如此。

如果还有其他不同的意见,请告诉我,我会非常感激。

请提供更多上下文信息。

 

广告
将在 10 秒后关闭
bannerAds