在日常开发中,我们常常会面对大量重复性的工作,比如:
这些代码通常遵循一定的结构以及实现模式,我们将这些内容称为模版代码,这些模版代码虽然重要,但是写起来枯燥,重复性高,容易出错。
简单来说,Codegen 就使用已经定义好的结构或者规范,比如:API 文档、数据库或者 Data Schema、接口定义等,自动生成代码,常见的用途包括:
一句话总结它的核心价值就是:把规范当作数据源,自动生成那些你原本要手写的重复代码。
在这篇文章里,我将主要分享我在实际项目中使用 Codegen 的三个典型场景,包括:
在通常的项目实践中,通常使用 RESTful API 来进行数据交互,后端使用 Swagger/OpenAPI 来维护接口文档,这时候我们可以用工具来把这些文档转化为前端可以直接使用的代码,比如请求函数、类型定义等。
我个人推荐 swagger-typescript-api,它使用简单,生成的代码也比较现代。
使用示例:
npm install --save-dev swagger-typescript-api
npx swagger-typescript-api generate --path ./swagger.json
更多使用示例以及详细文档可以点击进入项目仓库进行查看。
生成后的代码结构通常包含:
带来的好处:
这个实践的前置准备是:后端维护好一份完备的 Swagger 文档。
相关学习资源:
如果你用的是 GraphQL,那 codegen 就更天然适配了。GraphQL 本身就强调 schema 驱动开发,你定义了查询语句,工具就能根据它生成类型和 hooks。
我在项目中用的是 GraphQL Codegen,它支持多种客户端,比如 Apollo、React Query 等。
配置方式示例:
import type { CodegenConfig } from '@graphql-codegen/cli'
const config: CodegenConfig = {
overwrite: true,
schema: '../graphql-schema/schema.gql',
documents: 'src/**/*.graphql',
ignoreNoDocuments: true,
generates: {
'src/generated/graphql-hook.tsx': {
plugins: [
'typescript',
'typescript-operations',
'typescript-react-apollo',
],
},
},
}
export default config
在 npm scripts 中增加:
"generate": "graphql-codegen --config graphql-codegen.ts",
执行后即可生成代码,直接调用相应的 Hook 进行数据交互。
我在做一个桌面应用时使用了 Tauri,前端是 React + TypeScript,后端是 Rust。这个组合的一个难点就是:Rust 和 TypeScript 是两个完全独立的类型系统,怎么保证它们的数据结构一致?
我找到了一个非常好用的工具:typeshare。它可以把 Rust 的结构体转成多种语言的类型定义,其中就包括 TypeScript。
Rust 端定义:
use typeshare::typeshare;
#[typeshare]
#[derive(Serialize, Deserialize)]
pub struct User {
pub id: u32,
pub name: String,
}
生成后的 TypeScript 类型:
export interface User {
id: number
name: string
}
如果你想了解真实的项目应用,可以查看我的 Query Box 项目:https://github.com/zhnd/query-box,欢迎大家 Star。
Codegen 不是银弹,但在适合的场景里,它真的能显著提升开发效率:
在我的个人项目中,这种“自动化思维”已经变成了一个默认选项:只要能 codegen 的地方,我都会优先考虑自动生成,哪怕一开始配置起来稍微复杂一些,长期一定是值得的。
如果你还没试过 codegen,不妨从一个简单的 Swagger 或 GraphQL 项目开始。你会发现 —— 原来很多你每天写的代码,其实都可以不用写。
如果你对这方面有其他实践经验、遇到有趣的问题,欢迎一起交流 👋。我的 GitHub 页面在:https://github.com/zhnd。