news 2026/9/19 23:34:00

Gatsby GraphQL Typegen 完整指南:用自动生成类型告别手写查询类型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Gatsby GraphQL Typegen 完整指南:用自动生成类型告别手写查询类型

Gatsby GraphQL Typegen 完整指南:用自动生成类型告别手写查询类型

【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby

导读

本指南讲解 Gatsby 的GraphQL Typegen自动类型生成功能:只要在gatsby-config中开启graphqlTypegen,Gatsby 就会在gatsby develop时根据你的 GraphQL 查询与 schema 自动生成 TypeScript 类型(默认输出到src/gatsby-types.d.ts),并为你提供 IDE 内联提示(IntelliSense)、GraphQL 查询自动补全与 ESLint 校验。读完本文,你将掌握如何开启与配置该功能、使用全局Queries命名空间、配合 GraphQL fragments 复用类型、接入 VSCode GraphQL 插件以及用graphql-eslint强制查询命名规范。

适用前提:Gatsby 项目使用gatsby@4.15.0或更高版本,并已按 Gatsby with TypeScript 配置好 TypeScript。该功能默认只在gatsby develop期间生成文件(构建阶段不生成)。

前置条件

在开始之前,确认你的项目满足以下条件:

  • Gatsby 版本gatsby@4.15.0或更高版本(GraphQL Typegen 在gatsby@4.15.0中引入)。

  • 开启配置项:在gatsby-config中将graphqlTypegen设为true

    module.exports = { graphqlTypegen: true, }
  • tsconfig.json包含源码目录:项目中需要有tsconfig.json,且"include"需覆盖生成文件路径,例如:

    { "compilerOptions": { /* ... */ }, "include": ["./src/**/*"] }

    完整示例可参考仓库中的 examples/using-graphql-typegen/tsconfig.json,它额外包含了./gatsby-node.ts./gatsby-config.ts./plugins/**/*

  • 可选:如果你使用 VSCode,可安装 GraphQL 扩展 以获得查询自动补全(详见后文"配置 VSCode GraphQL 插件"一节)。

使用自动生成的Queries类型

为了让示例正常运行,请先在gatsby-configsiteMetadata中准备一个title字段:

module.exports = { siteMetadata: { title: `My Gatsby Site`, }, graphqlTypegen: true, }

示例项目的完整配置见 examples/using-graphql-typegen/gatsby-config.ts。

第一步:启动开发服务器

运行gatsby develop。当服务器就绪后,你会在终端底部看到一条日志:

Generating GraphQL and TypeScript types

这条日志来自 Gatsby 的 typegen 服务。从源码看,该服务依次执行三步写入:graphQLTypegen 会调用writeGraphQLSchema写入 schema、writeGraphQLFragments写入 fragments,最后调用writeTypeScriptTypes生成 TypeScript 类型,整个过程被包裹在 reporter 的活动计时器中。

第二步:查看生成的类型文件

Gatsby 会生成一个类型声明文件,默认位于src/gatsby-types.d.ts,其中包含你所有查询对应的 TypeScript 类型。你的tsconfig.json需要 include 该文件,这样就能在项目任何地方访问Queries命名空间(全局declare namespace Queries)。

第三步:创建一个使用类型的页面

src/pages/typegen.tsx创建新页面:

import * as React from "react" import { graphql, PageProps } from "gatsby" const TypegenPage = ({ data }: PageProps) => { return ( <main style={pageStyles}> <p>Site title: TODO</p> <hr /> <p>Query Result:</p> <pre> <code>{JSON.stringify(data, null, 2)}</code> </pre> </main> ) } export default TypegenPage export const query = graphql` query TypegenPage { site { siteMetadata { title } } } `

关键点:查询必须有名字(如query TypegenPage {}),否则自动类型生成无法工作。建议查询名与 React 组件同名,并使用 PascalCase 命名。你可以通过graphql-eslint(见下文)强制执行这一约定。

第四步:在组件中使用Queries命名空间

在 React 组件中访问Queries命名空间,并使用TypegenPageQuery类型:

({ data }: PageProps<Queries.TypegenPageQuery>)

当你像下面这样写出站点标题时,就能获得 TypeScript IntelliSense 提示:

<p>Site title: {data.site?.siteMetadata?.title}</p>

注意这里使用了可选链?.,原因见下文"Non-Nullable 类型"一节。

配置gatsby-config中的选项

除了布尔值,graphqlTypegen还可以设置为一个对象来细化配置:

module.exports = { graphqlTypegen: { typesOutputPath: `src/gatsby-types.d.ts`, documentSearchPaths: [`./gatsby-node.ts`, `./plugins/**/gatsby-node.ts`], }, }
配置项说明
typesOutputPath类型文件的输出路径。默认值为src/gatsby-types.d.ts。修改后请同步更新tsconfig.json"include",把新路径包含进去。
documentSearchPaths覆盖被扫描以提取 GraphQL 查询的文档搜索路径。默认值为./gatsby-node.ts./plugins/**/gatsby-node.ts(见 ts-codegen.ts)。

从源码看,这两个默认值定义在 ts-codegen.ts:DEFAULT_TYPES_OUTPUT_PATH = 'src/gatsby-types.d.ts'DEFAULT_DOCUMENT_SEARCH_PATHS = ['./gatsby-node.ts', './plugins/**/gatsby-node.ts']。同时,Joi 校验层(joi.ts)允许graphqlTypegen为布尔值或对象,且两个字段均带默认值,说明它们可省略。

另外,documentSearchPaths的机制值得说明:生成gatsby-node.ts中的查询类型时,Gatsby 使用loadDocuments+CodeFileLoader扫描这些路径,并通过pluckConfig仅提取来自gatsby包的graphql标签模板(见 ts-codegen.ts)。

Non-Nullable 类型

由于 Gatsby 推断所有字段(除非用户提供了显式 schema),字段默认都是可空的。这意味着在 GraphQL Typegen 中,字段可能为null——正如上面的示例,你必须写成data.site?.siteMetadata?.title,因为siteMetadatatitle都是可空的。

如果你确定siteMetadata.title始终存在,可以使用 Gatsby 的 schema 自定义 API 显式声明字段类型:

import { GatsbyNode } from "gatsby" export const createSchemaCustomization: GatsbyNode["createSchemaCustomization"] = ({ actions }) => { actions.createTypes(` type Site { siteMetadata: SiteMetadata! } type SiteMetadata { title: String! } `) }

!表示非空。关于如何显式定义类型,可阅读 Customizing the GraphQL schema guide。

生成代码的类型选项也印证了可空设计:ts-codegen.ts中设置avoidOptionals: truemaybeValue: 'T | null',即字段类型被生成为T | null而非可选属性(见 ts-codegen.ts)。

GraphQL fragments

Fragments 允许你在整个站点中复用 GraphQL 查询的片段,并把查询的特定部分与单个文件内聚。可参考 Using GraphQL fragments guide。

在 GraphQL Typegen 的语境下,fragments 让你能为查询的嵌套部分获得独立的 TypeScript 类型——因为每个 fragment 都会成为自己的 TypeScript 类型。你可以用这些类型来标注消费 GraphQL 数据的组件参数。

以下示例(同样来自 using-graphql-typegen 示例)展示了一个接收buildTime参数的Info组件。该组件和它的SiteInformationfragment 随后被用在src/pages/index.tsx中:

import * as React from "react" import { graphql } from "gatsby" const Info = ({ buildTime }: { buildTime?: any }) => { return ( <p> Build time: {buildTime} </p> ) } export default Info export const query = graphql` fragment SiteInformation on Site { buildTime } `
# Rest of the page above... query IndexPage { site { ...SiteInformation } }

这样就会生成一个SiteInformationFragmentTypeScript 类型,你可以直接在Info组件中使用:

const Info = ({ buildTime }: { buildTime?: Queries.SiteInformationFragment["buildTime"] }) => {}

仓库示例 examples/using-graphql-typegen/src/components/info.tsx 正是这样实现的,对应页面查询见 examples/using-graphql-typegen/src/pages/index.tsx。注意buildTime类型是可空的(?),这与前面讲的"推断字段默认可空"一致。此外,源码中为 typescript-operations 插件设置了exportFragmentSpreadSubTypes: true(见 ts-codegen.ts),这保证了 fragment 展开子类型会被导出。

Tips

  • 保存文件后类型才更新:当你给 GraphQL 查询新增字段时,需要保存文件,自动生成的文件才会更新——生成的文件只在文件保存时刷新。
  • 图片类型开箱即用:使用gatsby-plugin-image(以及 Image CDN)时,gatsbyImageDatagatsbyImage会自动获得正确的 TypeScript 类型。这是因为生成配置中内置了标量映射:GatsbyImageData: import('gatsby-plugin-image').IGatsbyImageDataDate: stringJSON: Record<string, unknown>(见 ts-codegen.ts)。
  • 建议加入.gitignore:推荐把src/gatsby-types.d.ts加入.gitignore,因为它是机器生成的代码,并且信息与页面查询等内容重复。生成文件头部也明确写有/* THIS FILE IS AUTOGENERATED. CHANGES WILL BE LOST ON SUBSEQUENT RUNS. */以及/* eslint-disable *//* prettier-ignore */标记(见 ts-codegen.ts),再次印证它不应被手改或提交。

配置 VSCode GraphQL 插件

  1. 在 VSCode 中安装 GraphQL 扩展。

  2. 在项目根目录创建graphql.config.js,内容如下:

    module.exports = require("./.cache/typegen/graphql.config.json")

    VSCode 扩展会读取graphql.config.js,并复用 Gatsby.cache目录中的自动生成文件。关于graphql.config.js的更多信息可查看 GraphQL Config 文档。

  3. 重启 VSCode,让 GraphQL 扩展生效。

  4. 启动开发服务器gatsby develop

  5. 打开任意查询(例如src/pages下的页面查询),使用Ctrl + Space(也可用Shift + Space作为替代快捷键)即可获得类似 GraphiQL 的自动补全。

该文件从哪来?从源码看,Gatsby 会生成三份产物到.cache/typegen/目录:schema.graphqlfragments.graphqlgraphql.config.json(见 file-writes.ts)。其中graphql.config.jsondocuments字段被设置为['src/**/**.{ts,js,tsx,jsx}', fragments 文件],即 IDE 会自动扫描src下的源码文件并合并 fragments,从而支持跨文件的自动补全。

多 GraphQL 项目

如果你的仓库包含多个 GraphQL 项目(包括 Gatsby),可以使用projects键配置:

module.exports = { projects: { site: require("./.cache/typegen/graphql.config.json"), other: { // other config } } }

子目录场景

如果 Gatsby 项目位于子目录(例如site),配置应改为:

module.exports = require("./site/.cache/typegen/graphql.config.json")

graphql-eslint

你可以选择使用graphql-eslint来 lint 你的 GraphQL 查询。它能无缝对接上一步创建的graphql.config.js

以下指南假设你还没有任何 ESLint 配置。如果你已经在使用 ESLint,需要自行适配你的配置,并参考graphql-eslint文档。

  1. 安装依赖:

    npm install --save-dev eslint @graphql-eslint/eslint-plugin @typescript-eslint/eslint-plugin @typescript-eslint/parser
  2. package.json中添加两个脚本:

    { "scripts": { "lint": "eslint --ignore-path .gitignore .", "lint:fix": "npm run lint -- --fix" }, }
  3. 创建.eslintrc.js配置 ESLint:

    module.exports = { root: true, overrides: [ { files: ['*.ts', '*.tsx'], processor: '@graphql-eslint/graphql', parser: "@typescript-eslint/parser", extends: [ "eslint:recommended", "plugin:@typescript-eslint/recommended" ], env: { es6: true, }, }, { files: ['*.graphql'], parser: '@graphql-eslint/eslint-plugin', plugins: ['@graphql-eslint'], rules: { '@graphql-eslint/no-anonymous-operations': 'error', '@graphql-eslint/naming-convention': [ 'error', { OperationDefinition: { style: 'PascalCase', forbiddenPrefixes: ['Query', 'Mutation', 'Subscription', 'Get'], forbiddenSuffixes: ['Query', 'Mutation', 'Subscription'], }, }, ], }, }, ], }
  4. 在项目根目录创建graphql.config.js

    module.exports = require("./.cache/typegen/graphql.config.json")
  5. 启动 Gatsby 开发服务器gatsby develop,确认.cache/typegen/graphql.config.json已生成。

现在你可以运行npm run lintnpm run lint:fix检查 GraphQL 查询(例如它们是否已命名)。通过@graphql-eslint/no-anonymous-operations规则,任何匿名的 GraphQL 操作都会被标记为错误,这正好呼应了前文"查询必须有名字"的硬性要求。

额外资源

  • Gatsby with TypeScript
  • VSCode GraphQL Plugin
  • IntelliJ GraphQL Plugin
  • gatsby-config Option
  • 可运行示例:examples/using-graphql-typegen(包含gatsby-config.tsgatsby-node.tsgraphql.config.jstsconfig.json与完整页面/组件源码)

【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 23:29:25

光伏电站智能预警系统:Web平台+LSTM+多源融合实战

简介&#xff1a;本资源是一份面向Web开发工程师、能源信息化系统设计人员及高校电力/自动化专业师生的技术分析文档&#xff0c;聚焦离网光伏电站集中监控痛点&#xff0c;提出一套基于Web平台的预警监控系统完整设计方案。文档深入剖析系统架构、数据采集逻辑、远程监控机制与…

作者头像 李华
网站建设 2026/9/19 23:28:44

Wireshark协议分析实战:ARP/ICMP/DNS/HTTP抓包与排错指南

简介&#xff1a;本资源是一份面向计算机网络专业本科生及初学者的Sniffer工具实践教学实验报告&#xff0c;聚焦网络协议分析、流量捕获与安全机制验证等核心能力培养。报告完整覆盖ICMP抓包分析、HTTP/HTTPS流量监控、ARP包构造与发送、ARP欺骗模拟及交换机端口镜像配置五大实…

作者头像 李华
网站建设 2026/9/19 23:28:17

BrewUI:可视化管理Homebrew,告别命令行依赖混乱

如果你经常用 macOS 开发&#xff0c;那大概率已经习惯了打开终端敲brew install xxx这类命令。Homebrew 确实好用&#xff0c;但用久了你会发现一个尴尬的点&#xff1a;依赖关系复杂到不敢轻易brew autoremove&#xff0c;一堆旧版本占着磁盘却不知道哪些能清&#xff0c;搜索…

作者头像 李华
网站建设 2026/9/19 23:25:43

Unity游戏Mod开发入门:BepInEx插件加载与Harmony补丁实战

很多人第一次接触Unity游戏的Mod开发&#xff0c;都是被英灵神殿、雨中冒险2这类热门游戏带进来的。打开NexusMods看到别人那些花里胡哨的功能&#xff0c;第一反应往往是“这到底是怎么做到的”&#xff0c;然后一搜教程&#xff0c;铺天盖地都是“下载BepInEx放到游戏目录”这…

作者头像 李华