TypeScript 单仓库入门
随着现代 Web 应用程序复杂性的增长,开发者越来越频繁地遇到代码管理问题。当一个项目由许多相互关联的模块组成——前端、后端、通用库——传统的独立仓库(polyrepo)方法可能导致代码重复、版本不同步以及重构困难。
单仓库(monorepo)是一种将多个项目的代码存储在一个仓库中的策略。结合 TypeScript,单仓库成为一个强大的工具:严格的类型化确保了整个技术栈内变更的安全性,而统一的构建系统简化了依赖管理。
在本文中,我们将探讨如何组织一个 TypeScript 单仓库:从基本结构到像 Nx 和 Turborepo 这样的高级工具。
TypeScript 项目使用单仓库的优势
在进入实践之前,我们先分析一下为什么单仓库对 TypeScript 项目特别有利:
- 统一的类型化 — TypeScript 允许在包之间重用接口和类型,无需重复。
- 原子提交 — API 及其使用者的变更可以在一个提交中完成,简化了审查和回滚。
- 简化的重构 — IDE(例如 VS Code)能正确处理整个仓库中的文件重命名和移动。
- 构建缓存 — 像 Nx 这样的工具会缓存编译结果,加速 CI/CD。
单仓库的基本结构
让我们从一个简单但有效的结构开始。创建一个根项目和一些包:
my-monorepo/├── packages/│ ├── shared/ # 通用类型和工具│ │ ├── src/│ │ ├── package.json│ │ └── tsconfig.json│ ├── server/ # 后端(例如 Express)│ │ ├── src/│ │ ├── package.json│ │ └── tsconfig.json│ └── web/ # 前端(React)│ ├── src/│ ├── package.json│ └── tsconfig.json├── package.json # 根 package.json├── tsconfig.base.json # 所有包的基础 tsconfig└── .gitignore根 package.json 应包含 workspace 配置。对于 npm 和 Yarn,它看起来像这样:
{ "name": "my-monorepo", "private": true, "workspaces": [ "packages/*" ], "scripts": { "build": "tsc --build", "clean": "tsc --build --clean" }}基础 tsconfig.base.json 设置通用的编译选项:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "declaration": true, "declarationMap": true, "sourceMap": true, "composite": true }}每个包扩展基础配置:
{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src" }, "include": ["src"]}依赖管理和 TypeScript paths
单仓库的关键问题之一是在包之间正确配置导入。我们不是将包发布到 npm,而是使用 TypeScript Project References 和 paths。
配置 Project References
在根 tsconfig.json 中添加对项目的引用:
{ "files": [], "references": [ { "path": "./packages/shared" }, { "path": "./packages/server" }, { "path": "./packages/web" } ]}现在,当启动