8.2 KiB
8.2 KiB
name, description, metadata
| name | description | metadata | ||
|---|---|---|---|---|
| tooling | 用于处理 GraphQL 操作的工具参考,包括代码生成与代码检查 |
|
工具
本参考文档涵盖了用于处理 GraphQL 操作的工具,包括代码生成和代码检查。
目录
GraphQL 代码生成器
概述
GraphQL 代码生成器可从你的 schema 和操作中生成 TypeScript 类型,确保整个应用程序的类型安全。
安装
npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node
基本配置
创建 codegen.ts:
// codegen.ts
import { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
overwrite: true,
schema: "<URL_OF_YOUR_GRAPHQL_API>",
// 假设所有源文件都在顶层的 `src/` 目录下——你可能需要根据你的文件结构调整此项
documents: ["src/**/*.{ts,tsx}"],
// 当没有文档时不以非零状态退出
ignoreNoDocuments: true,
generates: {
// 使用最适合你应用程序结构的路径
"./src/types/__generated__/graphql.ts": {
plugins: ["typescript", "typescript-operations", "typed-document-node"],
config: {
avoidOptionals: {
// 对可空字段使用 `null` 而非可选字段
field: true,
// 允许可空输入字段保持未指定状态
inputValue: false,
},
// 对未配置的标量使用 `unknown` 而非 `any`
defaultScalarType: "unknown",
// Apollo Client 始终包含 `__typename` 字段
nonOptionalTypename: true,
// Apollo Client 不会为根类型添加 `__typename` 字段,因此
// 不要为根操作类型生成 `__typename` 的类型。
skipTypeNameForRoot: true,
},
},
},
};
export default config;
运行生成
# 一次性生成
npx graphql-codegen
# 开发时的监听模式
npx graphql-codegen --watch
Package 脚本
{
"scripts": {
"codegen": "graphql-codegen",
"codegen:watch": "graphql-codegen --watch"
}
}
生成类型的使用
// 之前:手动类型定义
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`;
// 手动类型定义
interface GetUserData {
user: {
id: string;
name: string;
} | null;
}
const { data } = useQuery<GetUserData>(GET_USER, { variables: { id } });
// 之后:使用生成类型
import { useGetUserQuery } from "./generated/graphql";
const { data } = useGetUserQuery({ variables: { id } });
// data.user 现在是完整类型化的!
近操作文件生成
在操作文件旁边生成类型:
const config: CodegenConfig = {
schema: "http://localhost:4000/graphql",
documents: ["src/**/*.graphql"],
generates: {
"src/": {
preset: "near-operation-file",
presetConfig: {
extension: ".generated.ts",
baseTypesPath: "generated/graphql.ts",
},
plugins: ["typescript-operations", "typescript-react-apollo"],
},
"src/generated/graphql.ts": {
plugins: ["typescript"],
},
},
};
结果如下:
src/
components/
UserCard/
UserCard.graphql
UserCard.generated.ts # 该文件的生成类型
片段类型
// UserAvatar.graphql
// fragment UserAvatar on User {
// id
// name
// avatarUrl
// }
import { UserAvatarFragment } from "./UserAvatar.generated";
interface UserAvatarProps {
user: UserAvatarFragment;
}
export function UserAvatar({ user }: UserAvatarProps) {
return <img src={user.avatarUrl} alt={user.name} />;
}
ESLint GraphQL
安装
npm install -D @graphql-eslint/eslint-plugin
配置
// eslint.config.js(扁平配置)
import graphqlPlugin from "@graphql-eslint/eslint-plugin";
export default [
{
files: ["**/*.graphql"],
languageOptions: {
parser: graphqlPlugin.parser,
},
plugins: {
"@graphql-eslint": graphqlPlugin,
},
rules: {
"@graphql-eslint/known-type-names": "error",
"@graphql-eslint/no-anonymous-operations": "error",
"@graphql-eslint/no-duplicate-fields": "error",
"@graphql-eslint/naming-convention": [
"error",
{
OperationDefinition: {
style: "PascalCase",
forbiddenPrefixes: ["Query", "Mutation", "Subscription"],
},
FragmentDefinition: {
style: "PascalCase",
},
},
],
},
},
];
推荐规则
rules: {
// 语法与合法性
'@graphql-eslint/known-type-names': 'error',
'@graphql-eslint/known-fragment-names': 'error',
'@graphql-eslint/no-undefined-variables': 'error',
'@graphql-eslint/no-unused-variables': 'error',
'@graphql-eslint/no-unused-fragments': 'error',
'@graphql-eslint/unique-operation-name': 'error',
'@graphql-eslint/unique-fragment-name': 'error',
// 最佳实践
'@graphql-eslint/no-anonymous-operations': 'error',
'@graphql-eslint/no-duplicate-fields': 'error',
'@graphql-eslint/require-id-when-available': 'warn',
// 命名规范
'@graphql-eslint/naming-convention': ['error', { ... }],
}
Schema 感知规则
提供 schema 以实现高级验证:
{
files: ['**/*.graphql'],
languageOptions: {
parser: graphqlPlugin.parser,
parserOptions: {
schema: './schema.graphql',
// 或者
schema: 'http://localhost:4000/graphql',
},
},
}
IDE 扩展
VS Code
GraphQL:语言功能支持(GraphQL 基金会)
- 语法高亮
- Schema 类型的自动补全
- 跳转到定义
- 悬停文档
- 针对 schema 的验证
配置(.graphqlrc.yml):
schema: "http://localhost:4000/graphql"
documents: "src/**/*.{graphql,ts,tsx}"
Apollo GraphQL(Apollo)
- Apollo 特有功能
- Schema 注册表集成
- 性能洞察
JetBrains IDE
GraphQL 插件:
- 语法高亮
- Schema 感知的补全
- 验证
- 导航到定义
配置(.graphqlconfig):
{
"schemaPath": "./schema.graphql",
"includes": ["src/**/*.graphql"]
}
配置文件
常见的配置文件名:
.graphqlrc(JSON).graphqlrc.yml(YAML).graphqlrc.json(JSON)graphql.config.js(JavaScript)
# .graphqlrc.yml
schema: "http://localhost:4000/graphql"
documents: "src/**/*.graphql"
extensions:
codegen:
generates:
./src/generated/graphql.ts:
plugins:
- typescript
- typescript-operations
操作验证
针对 Schema 进行验证
# 使用 graphql-inspector
npx graphql-inspector validate ./src/**/*.graphql ./schema.graphql
CI 集成
# .github/workflows/graphql.yml
name: GraphQL 验证
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 安装依赖
run: npm ci
- name: 下载 schema
run: npx graphql-inspector introspect http://localhost:4000/graphql --write schema.graphql
- name: 验证操作
run: npx graphql-inspector validate './src/**/*.graphql' schema.graphql
- name: 检查破坏性变更
run: npx graphql-inspector diff schema.graphql http://localhost:4000/graphql
Pre-commit 钩子
// package.json
{
"lint-staged": {
"*.graphql": ["eslint --fix", "graphql-inspector validate ./schema.graphql"]
}
}
操作复杂度检查
# 检查查询复杂度
npx graphql-query-complexity-checker \
--schema ./schema.graphql \
--query ./src/queries/GetUser.graphql \
--max-complexity 100
持久化查询提取
生成用于生产环境的持久化查询:
// codegen.ts
const config: CodegenConfig = {
generates: {
"./persisted-queries.json": {
plugins: ["graphql-codegen-persisted-query-ids"],
config: {
output: "client",
algorithm: "sha256",
},
},
},
};
输出:
{
"abc123...": "query GetUser($id: ID!) { user(id: $id) { id name } }",
"def456...": "mutation CreatePost($input: CreatePostInput!) { ... }"
}