- 后端
- GraphQL
- API设计
【免费下载链接】type-graphql
Create GraphQL schema and resolvers with TypeScript, using classes and decorators!
TypeGraphQL 是一个基于 TypeScript 类与装饰器构建 GraphQL Schema 的 Node.js 框架(见 package.json 中的项目自述)。在实际项目中,我们往往希望把后端定义的 Args、Input 类(连同class-validator校验装饰器)或带辅助方法的 ObjectType 类复用到浏览器端客户端应用中。本指南以website/versioned_docs/version-0.17.0/browser-usage.md为核心,讲解如何在不引入完整 TypeGraphQL 运行时的情况下复用这些类,涵盖 Webpack(CRA/Cypress)、Angular(AoT)与 Next.js 三种场景的 Shim 配置,并深入源码说明其工作原理与体积收益。
为什么浏览器端不能直接引入 TypeGraphQL
TypeGraphQL 的职责是在服务端读取装饰器元数据、反射类型信息并最终生成 GraphQL Schema(核心实现位于 src/schema/schema-generator.ts 与 src/metadata/metadata-storage.ts)。它依赖 Node.js 运行时特性与大量服务端依赖,无法在浏览器中直接运行。
因此在浏览器工程(例如 Webpack 构建)里直接import ... from "type-graphql"时,打包器会尝试解析完整的 Node.js 模块依赖链,常常立刻报错,典型错误包括:
ERROR in ./node_modules/fs.realpath/index.jsutils1_promisify is not a function
(这两个错误信息同样出现在当前仓库的 docs/browser-usage.md 中。)
根本原因在于:客户端代码真正需要的只是那些装饰器函数本身(运行时是空操作)与部分类型的“占位符”,并不需要 Schema 生成、元数据存储、参数转换等整套服务端实现。
Decorator Shim 是什么
TypeGraphQL 为此提供了一个专用的“装饰器 Shim”——源码见 src/shim.ts。它只导出一系列空实现,例如:
dummyValue、dummyFn、dummyDecorator三个基础占位符(src/shim.ts);- 全部装饰器(
Arg、Args、Field、ObjectType、InputType、Query、Mutation、Resolver、Root、Ctx、Info、Subscription、UseMiddleware、Authorized、Directive、Extensions等)都被定义为返回空函数的dummyDecorator(src/shim.ts); registerEnumType、createUnionType、createParameterDecorator、createMethodMiddlewareDecorator等工厂函数被替换为无操作函数(src/shim.ts);Int、Float、ID、GraphQLISODateTime、GraphQLTimestamp等标量常量被替换为dummyValue(src/shim.ts)。
值得注意的细节是:这些导出的类型签名都与 src/index.ts 的完整导出保持一致(如export const Arg: typeof src.Arg = dummyDecorator),所以在浏览器端替换后 TypeScript 类型检查依然完全正常,装饰器在运行时也只是“空操作”,不影响类结构、属性与class-validator校验装饰器的正常行为。
在发布的 npm 包中,该 Shim 被暴露为独立的包入口点type-graphql/shim(对应./build/cjs/shim.js、./build/esm/shim.js与./build/typings/shim.ts,见 package.json);同时browser字段直接指向./build/cjs/shim.js(package.json),便于打包器按浏览器环境自动命中。构建流程会保留这份shim.ts源码以供 AoT 场景使用(见 package.json 中的postbuild脚本)。
使用 Shim 带来的另一个显著收益是包体积:客户端不再嵌入整个 TypeGraphQL 库代码,打包产物会明显更轻量。
方案一:Webpack 环境(CRA 及同类工具)
这是最通用的接入方式,原理是用 Webpack 的NormalModuleReplacementPlugin把对type-graphql的模块请求替换为type-graphql/shim。
在webpack.config.js中加入插件(配置写法与当前仓库 docs/browser-usage.md 及 src/shim.ts 头部注释中的示例一致):
module.exports = { // ... Webpack 其余配置 plugins: [ // ... 你已有的其他插件 new webpack.NormalModuleReplacementPlugin(/type-graphql$/, resource => { resource.request = resource.request.replace(/type-graphql/, "type-graphql/shim"); }), ], };要点说明:
- 正则
/type-graphql$/只匹配以type-graphql结尾的模块请求(即从type-graphql主入口导入),因此不会误伤对type-graphql/shim自身的引用。 resource.request.replace(/type-graphql/, "type-graphql/shim")在匹配到的请求上原地改写模块路径,把主入口替换为 Shim 入口。- 在 Create React App(CRA)这类内部封装了 Webpack、不直接暴露配置的项目中,可以使用
react-app-rewired或craco之类的工具拿到并扩充这份配置。 - 如果你使用 Cypress 做端到端测试,且测试代码中复用了这些共享类,可以采用同样的 Webpack 替换技巧,只需让 Cypress 的预处理器使用这份 Webpack 配置——例如官方维护的
cypress-webpack-preprocessor插件。
方案二:Angular 等 AoT 编译器场景(tsconfig paths)
部分 TypeScript 工程(最典型的是 Angular)在 AoT 编译时要求提供完整的*.ts源文件,而不是仅编译好的*.js与*.d.ts声明文件。这时 Webpack 替换方案不再适用,需要改用 TypeScript 的路径映射,把type-graphql直接指向 Shim 的 TypeScript 源码文件。
在项目的tsconfig.json中配置如下(写法与当前仓库 docs/browser-usage.md 一致):
{ "compilerOptions": { "baseUrl": ".", "paths": { "type-graphql": ["node_modules/type-graphql/build/typings/shim.ts"] } } }要点说明:
baseUrl是paths解析的基准目录,这里设为项目根目录.。paths中的type-graphql键使编译器把一切import ... from "type-graphql"解析为node_modules/type-graphql/build/typings/shim.ts——这正是发布包中特意保留的shim.ts源文件(package.json 的postbuild脚本将其从 src/shim.ts 复制到build/typings下)。- 同理,这类手法也适用于其他对模块解析方式有类似要求的编译器或构建工具链。
方案三:Next.js 及同类前后端一体框架
Next.js 作为同时承担服务端渲染与客户端打包的框架,情况要复杂一些:页面默认在服务端预渲染(pre-render)。在开发模式下,next.config.js中的webpack: {}配置会被跳过,因此服务端会打包完整的type-graphql;但客户端打包在开发与生产模式下都会经过 Webpack,所以仍然需要为客户端做模块重定向。
官方推荐的“最简单方式”同样是走tsconfig.json路径映射——与方案二完全一致,在compilerOptions中加入同样的键:
{ "compilerOptions": { "baseUrl": ".", "paths": { "type-graphql": ["node_modules/type-graphql/build/typings/shim.ts"] } } }光改tsconfig.json还不够,因为 Node.js 运行时(服务端进程)本身并不认识 TypeScript 的paths映射,此时服务端代码中的import "type-graphql"仍会解析到完整模块。需要借助tsconfig-paths在运行时注册路径别名:
npm install -D tsconfig-paths然后通过环境变量启用(让 Node.js 启动时先加载tsconfig-paths/register模块,读取并应用tsconfig.json中的paths映射):
NODE_OPTIONS="-r tsconfig-paths/register"配置完成后,客户端与服务端都会按 Shim 解析type-graphql:既避免了服务端在预渲染时把完整库误打进客户端包,也让共享类在两端都能正常通过编译。
三种方案的适用场景对比
| 场景 | 推荐方案 | 关键配置点 |
|---|---|---|
| CRA 及一般 Webpack 工程 | WebpackNormalModuleReplacementPlugin | 将type-graphql替换为type-graphql/shim |
| Cypress 端到端测试 | 同样的 Webpack 替换 | 通过cypress-webpack-preprocessor应用配置 |
| Angular 等 AoT 编译器 | tsconfig.json路径映射 | paths指向build/typings/shim.ts |
| Next.js 前后端一体 | tsconfig.json路径映射 +tsconfig-paths | 环境变量NODE_OPTIONS="-r tsconfig-paths/register" |
补充:Webpack 场景也可以直接利用
package.json中的browser字段(package.json),该字段已指向./build/cjs/shim.js,部分支持browser字段的打包器会据此自动选择浏览器入口,可作为手工替换之外的辅助手段。
使用 Shim 的注意事项
- Shim 只保证“编译通过”:装饰器均为空操作,运行时不会产生任何 Schema 或元数据,因此它只适合复用类定义(配合
class-validator校验装饰器、自定义辅助方法等),不能替代服务端完成任何 GraphQL 逻辑。 - 类型安全不受影响:由于 Shim 导出的类型签名与原模块一致(src/shim.ts),前端代码中的类型推导、IDE 提示与编译期检查均保持完整。
- 版本对齐:不同版本 TypeGraphQL 的 Shim 入口路径可能不同(例如 0.16.0 文档中曾使用
type-graphql/browser-shim,见 website/versioned_docs/version-0.16.0/browser-usage.md),而 0.17.0 及后续版本统一为type-graphql/shim(CHANGELOG.md 中记录了“将 Shim 作为包入口点type-graphql/shim暴露”这一变更),请以你实际安装版本发布说明为准。 - Shim 本身不属于测试覆盖范围:仓库的 Jest 配置在统计覆盖率时明确排除了 src/shim.ts(见 jest.config.cts),因为它只是面向打包器与编译器的占位实现。
小结
在浏览器端复用 TypeGraphQL 装饰器类,核心思路是用“装饰器 Shim”替换完整库:Webpack 系列项目使用NormalModuleReplacementPlugin指向type-graphql/shim;Angular 等 AoT 工程在tsconfig.json中用paths指向build/typings/shim.ts;Next.js 除路径映射外还需配合tsconfig-paths与NODE_OPTIONS环境变量。无论哪种方式,最终都能让共享类在客户端正常编译运行,同时让前端包体积显著减小——这正是 src/shim.ts 存在的价值。
- 后端
- GraphQL
- API设计
【免费下载链接】type-graphql
Create GraphQL schema and resolvers with TypeScript, using classes and decorators!
相关推荐
TypeGraphQL 浏览器端使用指南:借助 decorator shim 复用类定义并显著减小打包体积
TypeGraphQL 浏览器端使用指南:借助 decorator shim 复用类定义并显著减小打包体积 导读 在服务端用 TypeGraphQL 以类和装饰
后端GraphQLAPI设计Kimi Code CLI 用户文档维护指南:gen-docs Skill 驱动的双语文档同步工作流
Kimi Code CLI 用户文档维护指南:gen docs Skill 驱动的双语文档同步工作流 Kimi Code CLI 的官方用户文档托管在仓库的 d
后端GraphQLAPI设计TypeGraphQL 浏览器端使用指南:借助 Decorator Shim 在 Web 客户端复用共享类
TypeGraphQL 浏览器端使用指南:借助 Decorator Shim 在 Web 客户端复用共享类 TypeGraphQL 是一个基于 TypeScri
后端GraphQLAPI设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考