Monorepo 项目是一种将多个相关应用、服务或库统一存放在同一个代码仓库的管理方式。它不同于传统的多仓库(Polyrepo),通过集中化的结构提升协作效率。在 monorepo 中,所有项目共享统一的依赖、构建工具和配置文件,开发者可以跨项目进行原子化提交和大规模重构,避免版本冲突。常见目录结构包括 packages/ 存放公共库、apps/ 存放应用,以及统一的 tsconfig.base.json 和 pnpm-workspace.yaml。这种模式在大型团队和复杂系统中尤为常见,
1. 项目结构
markdown
monorepo-root/
├─ .vscode/
├─ launch.json VSCode启动文件
├─ settings.json VSCode配置文件
|
├─ packages/
│ ├─ foo/ # 库foo
│ │ ├─ src/ # 源代码目录
| | | └─ index.ts # TypeScript代码文件
│ │ └─ package.json # 包配置文件
│ └─ bar/ # 库bar
│ ├─ src/
│ └─ package.json│
│
├─ apps/
│ └─ app1/ # 应用
│ ├─ src/ # 源代码目录
| | └─ index.ts # TypeScript代码文件
│ └─ package.json # 包配置文件
│
├─ pnpm-workspace.yaml # Workspace 配置
├─ package.json # 顶层依赖/脚本
├─ tsconfig.base.json # 基础 TypeScript 配置
└─ tsconfig.json # 顶层 TypeScript 配置
2. 根目录配置文件
2.1 pnpm-workspace.yaml
pnpm-workspace.yaml 是 pnpm monorepo 的核心配置文件,用于声明哪些目录属于同一个工作区。它通过 packages 字段列出路径模式(如 packages/、apps/),让 pnpm 自动识别子项目并共享依赖。这样可以实现 统一安装依赖、跨包联动开发、避免重复安装,是管理大型多包仓库的关键机制。
yaml
packages:
- 'packages/*'
- 'apps/*'
2.2 package.json
package.json 是 Node.js 与前端项目的核心配置文件,用于描述包的基本信息和依赖关系。它包含 name、version、scripts、dependencies 等字段,帮助开发者管理项目生命周期。通过 scripts 可以定义构建、测试、启动命令;通过 dependencies 和 devDependencies 管理运行时与开发依赖;还可配置 main、types、exports 等入口信息。它是 npm、pnpm、yarn 等包管理工具识别和操作项目的关键文件。
json
{
"name": "monorepo-root",
"private": true,
"scripts": {
"build": "pnpm -r run build"
}
}
2.3 tsconfig.base.json
一个基础的 tsconfig.base.json 通常作为 monorepo 或多项目的统一配置文件,供各子包通过 "extends" 继承。它的作用是集中管理编译选项,避免重复配置。
json
{
"compilerOptions": {
"module": "ESNext",
"target": "esnext",
"types": [],
"sourceMap": true,
"declaration": true,
"declarationMap": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noImplicitOverride": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true,
"strict": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"moduleDetection": "force",
"skipLibCheck": true,
}
}
2.4 tsconfig.json
tsconfig.json 是 TypeScript 项目的核心配置文件,用于定义编译器行为和项目结构。它包含 compilerOptions(如 target、module、strict)、include 与 exclude(控制编译范围)、以及 references(支持多项目依赖)。通过它可以统一代码检查规则、指定输入输出目录、生成类型声明文件,并支持 monorepo 的项目引用。tsconfig.json 让团队在大型项目中保持一致的编译标准,是 TypeScript 开发的基础配置文件。
json
{
"extends":"./tsconfig.base.json"
}
3. 项目foo
index.ts
typescript
export function greet(timeOfDay:string){
console.log(`Good ${timeOfDay}`);
}
tsconfig.json:
json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "./lib",
"rootDir": "./src"
},
"include": ["src"]
}
package.json:
json
{
"name": "@jaydenai/foo",
"exports": {
".": {
"require": "./lib/index.js",
"import": "./lib/index.js",
"types": "./lib/index.d.ts"
}
},
"files": [
"lib",
"package.json"
] ,
"scripts": {
"build": "tsc -p tsconfig.json"
}
}
4. 项目bar(引用foo)
index.ts
typescript
import {greet} from '@jaydenai/foo'
export function greet4Morning(){
greet("morning");
}
export function greet4Afternoon(){
greet("afternoon");
}
export function greet4Evening(){
greet("evening");
}
tsconfig.json:
json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "./lib",
"rootDir": "./src"
},
"include": ["src"],
"references": [
{ "path": "../foo" }
]
}
package.json:
json
{
"name": "@jaydenai/bar",
"exports": {
".": {
"require": "./lib/index.js",
"import": "./lib/index.js",
"types": "./lib/index.d.ts"
}
},
"files": [
"lib",
"package.json"
] ,
"dependencies": {
"@jaydenai/foo":"workspace:*"
},
"scripts": {
"build": "tsc -p tsconfig.json"
}
}
5. 应用app1(引用bar)
index.ts
typescript
import {greet4Morning, greet4Afternoon,greet4Evening} from '@jaydenai/bar'
greet4Morning();
greet4Afternoon();
greet4Evening()
tsconfig.json:
json
{
"extends":"../../tsconfig.base.json",
"include": ["src"],
"references": [
{ "path": "../../packages/bar" }
]
}
package.json:
json
{
"name": "@jaydenai/app1",
"dependencies": {
"@jaydenai/bar":"workspace:*"
},
"scripts": {
"build": "tsc -p tsconfig.json"
}
}
6. VSCode相关配置
launch.json(启动当前选中文件进行调试):
json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug App with Cordis Source",
"type": "node",
"request": "launch",
"runtimeExecutable": "npx",
"runtimeArgs": ["tsx"],
"args": [
"${file}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
settings.json(屏蔽构建的产物)
json
{
"files.exclude": {
"**/node_modules": true,
"**/lib": true,
"**/*.d.ts": true,
"**/*.js": true,
"**/*.map": true,
"**/*.tsbuildinfo": true,
"**/pnpm-lock.yaml": true
}
}
7. Debug apps/app1/src/index.ts
输出
bash
Good morning
Good afernoon
Good evening