从0搭建monorepo项目

32 阅读5分钟

前言

什么是 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 安装代码规范和提交规范插件

这里我们使用oxlintoxfmt,底层由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版✨)