前言
什么是 Monorepo
Monorepo(单一代码仓库)是一种软件开发模式,它将多个项目或模块的代码存储在一个统一的版本控制仓库中,而不是分散在多个独立的仓库中。这种结构允许团队共享代码、依赖项和工具链,同时简化协作和依赖管理。
Monorepo 的作用
-
代码共享与复用:不同项目可以轻松引用同一仓库中的公共库或组件,减少重复代码。
-
简化依赖管理:依赖关系在仓库内直接引用,避免版本冲突和复杂的包管理问题。
-
统一构建与测试:所有项目共享同一套构建、测试和部署流程,提高开发效率。
-
跨团队协作:开发者可以更方便地查看和修改其他项目的代码,促进跨功能协作。
-
原子级提交:变更可以跨多个项目一次性提交,确保依赖更新的一致性。
Monorepo 适用于中大型项目或需要高度协同的团队,但也可能带来仓库体积增长和权限管理复杂度增加的问题。合理使用工具(如 pnpm turbo)能有效优化 Monorepo 的工作流。
提示:以上前言都是由ai生成,了解一下即可
项目地址
一、开始搭建
1 初始化项目
pnpm init
2 安装ts等插件
pnpm add typescript @types/node -D -w
-w 表示给根目录安装
配置tsconfig.json
{
"compilerOptions": {
// === 编译目标配置 ===
"target": "esnext",
// 编译后的 JavaScript 版本(ES2020 支持现代浏览器)
"useDefineForClassFields": true,
// 使用 ECMAScript 标准的类字段行为
"module": "ESNext",
// 使用最新的 ES 模块系统
"lib": ["ES2020", "DOM", "DOM.Iterable"],
// 可用的库类型定义(ES2020 API + 浏览器 DOM API)
"skipLibCheck": true,
// 跳过 .d.ts 文件的类型检查(加快编译速度)
// === 模块解析配置 ===
"moduleResolution": "bundler",
// 使用打包工具的模块解析策略(Vite/Rollup)
"allowImportingTsExtensions": true,
// 允许导入 .ts 文件时带扩展名
"resolveJsonModule": true,
// 允许导入 JSON 文件
"isolatedModules": true,
// 确保每个文件都可以独立编译(Vite 要求)
"noEmit": true,
// 不生成编译后的文件(由 Vite 处理)
"jsx": "preserve",
// 保留 JSX 语法不转换(由 Vite 处理)
// === 类型检查配置 ===
"strict": true,
// 开启所有严格类型检查选项
"noUnusedLocals": true,
// 检查未使用的局部变量
"noUnusedParameters": true,
// 检查未使用的函数参数
"noFallthroughCasesInSwitch": true,
// 检查 switch 语句的 fallthrough 情况
// === 路径映射配置 ===
"baseUrl": ".",
"paths": {
//后面添加
}
},
// 包含的文件范围
//后面添加
"include": [],
// 排除的文件范围
"exclude": ["node_modules", "**/dist"]
// 排除依赖和构建产物
}
3 创建workspace
创建pnpm-workspace.yaml文件,输入内容
packages:
- "packages/*"
- "apps/*"
此处具体内容为 你的项目里哪些文件夹是需要管理的「代码包 / 模块」
4 安装turbo
turbo官网 turbo目前比较合适处理monorepo的工具,当然也有nx之类的,但是nx比较繁琐,这里就用turbo
pnpm add turbo -D -w
创建turbo.json文件
{
"$schema": "https://turborepo.dev/schema.json",
"tasks": {
"build": {
"outputs": ["dist/**"]
},
// 处理
"build:watch": {
"cache": false, //
"persistent": true //持久型
},
"check-types": {
"dependsOn": ["^check-types"]
},
"dev": {
"persistent": true,
"cache": false
}
}
}
5 安装代码规范和提交规范插件
这里我们使用oxlint和oxfmt,底层由rust编写,速度更块,适合monorepo的项目
pnpm add oxfmt oxlint simple-git-hooks cz-git @commitlint/cli @commitlint/config-conventional -D -w
simple-git-hooks 简化版的husky 修改==package.json== 文件
{
"name": "monorepo",
"version": "1.0.0",
"description": "monorepo project",
"keywords": [],
"license": "ISC",
"author": "",
"main": "index.js",
"scripts": {
"lint": "oxlint",
"lint:fix": "oxlint --fix",
"fmt": "oxfmt",
"fmt:check": "oxfmt --check",
"commit": "czg",
"prepare": "simple-git-hooks"
},
"devDependencies": {
"@commitlint/cli": "^20.4.3",
"@commitlint/config-conventional": "^20.4.3",
"@types/node": "^25.3.3",
"cz-git": "^1.12.0",
"czg": "^1.12.0",
"oxfmt": "^0.36.0",
"oxlint": "^1.51.0",
"simple-git-hooks": "^2.13.1",
"turbo": "^2.8.13",
"typescript": "^5.9.3"
},
"simple-git-hooks": {
"pre-commit": "npx lint-staged",
"commit-msg": "npx commitlint --edit ${1}"
},
"lint-staged": {
"*.{js,ts,tsx,vue,json}": [
"oxlint --fix",
"oxfmt"
]
},
"packageManager": "pnpm@10.22.0",
"commitizen": {
"path": "node_modules/cz-git"
},
"engines": {
"node": ">=22.17.0",
"pnpm": ">=10.0.0"
}
}
这里顺便添加了一下engines,保证node版本和pnpm版本 创建.npmrc文件 严格校验node版本
# .npmrc
engine-strict=true
配置oxlint
创建.oxlintrc.json文件 详细可查看oxlint
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "warn"
},
"rules": {
"eslint/no-unused-vars": "error",
// 不允许使用any
"typescript/no-explicit-any": "off",
// 不允许使用var
"no-var": "error"
}
}
配置oxfm
创建.oxfmtrc.json文件 详情查看oxfmt
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"trailingComma": "es5",
"semi": false,
"tabWidth": 2,
"useTabs": false
}
配置.vscode
要实现保存自动格式化和校验,需要在.vscode中配置,相信大家之前用eslint的时候肯定是知道的
在.vscode分别创建extensions.json和settings.json文件
extensions.json:
{
"recommendations": ["oxc.oxc-vscode"]
}
settings.json
{
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "always"
}
}
配置commitlint
详情可见🎉🎉🎉从零构建react+vite6+ts+prettier+stylelint+husky+Lint-staged+Commitlint(2025版✨)
这里不再赘述
6 创建公共方法
初始化
在packages创建公共方法文件,当然不一定非得在这个文件夹下,只要文件夹配置在pnpm-workspace.yaml都是可以的
创建一个utils文件夹 使用pnpm初始化项目,同时安装tsdown
--filter 包名 :表示只给这个包安装
pnpm add -D tsdown --filter @monorepo/utils
package.json
{
"name": "@monorepo/utils",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build:watch": "tsdown --watch",
"build": "tsdown"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.22.0",
"devDependencies": {
"tsdown": "^0.20.3"
}
}
配置打包文件
创建tsdown.config.ts文件
import { defineConfig } from "tsdown";
export default defineConfig({
entry: ["./index.ts"],
format: "esm",
dts: true, //生成声明文件
clean: true,
platform: "neutral",
});
配置打包
当上述文件配置好之后,我们可能需要实现批量打包功能,此时我们需要修改根目录的package.json文件
{
"name": "monorepo",
"version": "1.0.0",
"description": "monorepo project",
"keywords": [],
"license": "ISC",
"author": "",
"main": "index.js",
"scripts": {
"lint": "oxlint",
"lint:fix": "oxlint --fix",
"fmt": "oxfmt",
"fmt:check": "oxfmt --check",
"build": "turbo run build",
"build:vue": "turbo run build --filter=vue-project",
"build:utils": "turbo run build --filter=@monorepo/utils",
"build:utils:watch": "turbo run build:watch --filter=@monorepo/utils",
"commit": "czg",
"prepare": "simple-git-hooks"
},
"devDependencies": {
"@commitlint/cli": "^20.4.3",
"@commitlint/config-conventional": "^20.4.3",
"@types/node": "^25.3.3",
"cz-git": "^1.12.0",
"czg": "^1.12.0",
"oxfmt": "^0.36.0",
"oxlint": "^1.51.0",
"simple-git-hooks": "^2.13.1",
"turbo": "^2.8.13",
"typescript": "^5.9.3"
},
"simple-git-hooks": {
"pre-commit": "npx lint-staged",
"commit-msg": "npx commitlint --edit ${1}"
},
"lint-staged": {
"*.{js,ts,tsx,vue,json}": [
"oxlint --fix",
"oxfmt"
]
},
"packageManager": "pnpm@10.22.0",
"commitizen": {
"path": "node_modules/cz-git"
},
"engines": {
"node": ">=22.17.0",
"pnpm": ">=10.0.0"
}
}
此时当我们在根目录执行pnpm build的时候,会将我们在worksapce的文件全部进行打包
当然也支持单个构建,比如pnpm build:utils
总结
这就搭建了一个虽然简单,但算是比较全面的monorepo项目
此类文章不经常写,所以写的不太好见谅
参考
🎉🎉🎉从零构建react+vite6+ts+prettier+stylelint+husky+Lint-staged+Commitlint(2025版✨)