Monorepo 架构以及工具选型、搭建

作者:颜酱日期:2025/11/28

Monorepo(Monolithic Repository,单体仓库)是一种代码管理策略,核心是将一个项目的所有相关代码(包括多个应用、库、工具链等)集中存储在单个代码仓库中,而非按模块拆分到多个独立仓库(Multirepo)。

📑 目录

  • 快速参考
  • 什么是 Monorepo
    • Monorepo vs Multirepo
    • Monorepo 的优缺点
    • 经典案例
  • 何时使用 Monorepo
  • 工具选型
    • 工作区管理工具
    • 任务调度工具
    • 版本管理工具
    • 代码质量工具
  • 实战搭建
    • 1. 初始化基础环境
    • 2. 配置 pnpm 工作区
    • 3. 配置 Turbo
    • 4. 根目录 package.json 配置
    • 5. 搭建核心包
    • 6. 搭建文档站点
    • 7. 搭建示例项目
    • 8. 核心命令使用
    • 9. 版本管理与发布
  • 高级配置
    • Turbo 缓存优化
    • CI/CD 集成
    • 依赖管理策略
  • 最佳实践
  • 常见问题

快速参考

工具选型速查表

工具类型推荐工具适用场景备选方案
包管理器pnpm workspace磁盘效率高、安装速度快npm workspace、yarn workspace
任务调度Turbo增量构建、并行任务、缓存Nx(企业级)、Rush(大型项目)
版本管理Changesetmonorepo 友好的版本管理release-it(单包)、Lerna(传统)

快速开始

1# 1. 初始化项目
2mkdir your-project && cd your-project
3pnpm init -y
4
5# 2. 安装 Turbo
6pnpm add turbo -D -w
7
8# 3. 配置工作区
9# 创建 pnpm-workspace.yaml
10
11# 4. 配置 Turbo
12# 创建 turbo.json
13
14# 5. 创建子包
15mkdir -p packages/core docs examples/basic
16

什么是 Monorepo

简单类比

  • Multirepo:像多个独立的文件夹,每个项目 / 库单独存放(比如 reactreact-domreact-router 各一个仓库)
  • Monorepo:像一个大文件夹,里面按功能分类存放所有相关项目(比如 Facebook 的 facebook/react 仓库,包含 React 核心、文档、示例、相关工具等所有代码)

常用结构

1monorepo-root/
2├── packages/          # 所有可复用包(库、工具)
3   ├── utils/         # 通用工具库
4   ├── components/     # UI 组件库
5   └── cli/           # 命令行工具
6├── apps/              # 可部署应用
7   ├── web/           # 网页应用
8   └── admin/         # 管理后台
9├── scripts/           # 全局构建/测试脚本
10├── package.json       # 根项目配置(依赖、脚本)
11└── pnpm-workspace.yaml # 工作区配置(pnpm 为例)
12

Monorepo vs Multirepo

对比维度Multirepo(多仓库)Monorepo(单仓库)
依赖管理重复安装,版本不一致,易冲突共享依赖,版本统一,减少冗余
跨项目引用需发布 npm / 用相对路径,同步修改繁琐本地直接引用,修改实时生效,无需发布
工程化规范各仓库独立配置,维护成本高根目录统一配置,所有子项目继承
代码复用复制粘贴或发布私有包,复用成本高仓库内直接复用,抽离库更便捷
版本管理与发布手动协调多包版本(如 A 依赖 B,B 升级后 A 需手动更新)工具自动管理版本依赖(如 Changeset),批量发布
协作效率跨仓库 PR 联动复杂,代码审查分散所有代码在一个仓库,PR 集中,协作更高效

Monorepo 的优缺点

优点

  • 高效协作:所有代码集中管理,跨项目修改无需切换仓库,PR 集中审查
  • 规范统一:工程化配置(lint、测试、构建)全局统一,降低维护成本
  • 依赖优化:共享依赖减少安装体积,版本统一避免冲突
  • 代码复用:子包间直接引用,无需发布,迭代速度快

缺点

  • 仓库体积增大:随着项目增多,仓库体积会变大,但现代 Git(如 Git LFS)可缓解
  • 构建速度:大型 Monorepo 全量构建较慢,需借助 Turborepo 等工具实现增量构建和缓存
  • 权限控制:难以对单个子包进行精细化权限控制(如需控制,可结合 Git 子模块或企业级工具如 GitLab Enterprise)

经典案例

前端 Monorepo 经典案例:

  • Reactfacebook/react 仓库包含 React 核心、React DOM、React Server Components 等所有相关代码
  • Vuevuejs/core 仓库包含 Vue 3 核心、编译器、运行时等
  • Vitevitejs/vite 仓库包含 Vite 核心、官方插件(如 @vitejs/plugin-react)等
  • Tailwind CSStailwindlabs/tailwindcss 仓库包含核心库、CLI、插件等

何时使用 Monorepo

当你的项目满足以下 2 个及以上条件时,优先选择 Monorepo:

  • ✅ 需拆分独立模块(核心包 + 文档 + 示例是典型场景)
  • ✅ 模块间有依赖关系(如示例依赖核心包、文档引用核心包 API)
  • ✅ 需统一构建、测试、发布流程
  • ✅ 追求高效开发(增量构建、并行任务)

何时不使用 Monorepo

  • ❌ 单一核心包 + 简单 README 文档(单包架构足够)
  • ❌ 子包之间完全独立,无依赖关系
  • ❌ 团队规模小,维护成本高

工具选型

工作区管理工具

负责管理多包的依赖安装、路径映射、脚本执行,主流选择:

工具磁盘效率安装速度monorepo 支持适用场景
pnpm workspace⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐推荐,生态最优
npm workspace⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐npm 7+ 原生支持
yarn workspace⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐Yarn 1.x 传统方案
Lerna⭐⭐⭐⭐⭐⭐⭐⭐⭐早期方案,已过时

选型建议

  • 推荐:pnpm workspace(磁盘效率高、安装速度快、生态完善)
  • 备选:npm workspace(npm 7+ 原生支持,无需额外配置)

核心特性

  • pnpm workspace:轻量、快速,原生支持 Monorepo,通过 pnpm-workspace.yaml 配置子项目路径,自动处理包之间的软链接,安装依赖时复用缓存,效率极高
  • Yarn Workspaces:与 pnpm 功能类似,支持 workspace:* 语法声明内部依赖
  • Lerna:早期流行的 Monorepo 工具,可搭配 npm/yarn 使用,擅长版本管理和发布,但依赖安装效率不如 pnpm

任务调度工具

需支持「多包构建」「增量构建」「依赖顺序构建」,避免每次全量构建:

工具增量构建并行任务缓存机制配置复杂度适用场景
Turbo⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐中小型项目(推荐)
Nx⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐大型企业级项目
Rush⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐超大型项目

选型建议

  • 中小型项目:Turbo(推荐,配置简单,性能优秀)
  • 大型企业级项目:Nx(功能强大,但配置复杂)
  • 超大型项目:Rush(微软开源,适合超大型 monorepo)

核心特性

  • Turbo:高性能构建系统,可缓存构建结果,并行执行任务(构建、测试、lint),大幅提升大型 Monorepo 的构建速度
  • tsup:支持多入口、增量构建,适配 TypeScript 项目,可快速构建多个子包
  • Rollup/Vite:适合构建库或应用,支持 Tree-shaking,Vite 还能提供开发时热更新

版本管理工具

解决多包版本联动、CHANGELOG 自动生成、npm 发布等问题:

工具monorepo 支持多包版本同步自动化程度配置复杂度适用场景
Changeset⭐⭐⭐⭐⭐✅ 自动同步⭐⭐⭐⭐⭐⭐多包项目(推荐)
release-it⭐⭐⭐❌ 需手动⭐⭐⭐⭐⭐⭐⭐⭐⭐单包项目、简单场景
Lerna⭐⭐⭐✅ 支持⭐⭐⭐⭐⭐传统方案

选型建议

  • 多包项目、需要版本同步:Changeset(推荐)
  • 单包项目、追求自动化:release-it
  • 简单场景、快速发布:release-it

核心特性

  • Changeset:轻量、易用,支持按子包提交变更记录,自动计算版本号(语义化版本),生成 CHANGELOG,批量发布子包
  • release-it:可搭配 Changeset 使用,提供交互式发布流程,支持 GitHub 标签、发布说明等

代码质量工具

统一管理 lint、测试、格式化:

工具类型推荐工具核心功能
代码规范ESLint + Prettier根目录配置,所有子项目共享规则,可通过 eslint-config-xxx 抽离自定义规则
测试框架Vitest / Jest统一测试框架,支持跨包测试,可在根目录运行所有子项目的测试用例
Git HooksHusky + lint-staged提交代码前自动执行 lint 和测试,保障代码质量

实战搭建

以下是最简搭建流程,基于 pnpm(生态最优)+ Turbo + tsup(核心包打包)+ VitePress(文档)+ Vitest(测试)

1. 初始化基础环境

1# 创建项目根目录
2mkdir your-project && cd your-project
3
4# 初始化根目录 package.json
5pnpm init -y
6
7# 安装 Turbo(任务调度)
8pnpm add turbo -D -w  # -w 表示安装到根目录(workspace-root)
9

2. 配置 pnpm 工作区

创建 pnpm-workspace.yaml

1# pnpm-workspace.yaml
2packages:
3  - 'packages/*' # 核心包(可发布)
4  - 'docs' # 文档站点(不发布)
5  - 'examples/*' # 示例项目(不发布)
6

3. 配置 Turbo

创建 turbo.json

1{
2  "$schema": "https://turbo.build/schema.json",
3  "globalDependencies": ["package.json", "turbo.json"],
4  "pipeline": {
5    "build": {
6      "dependsOn": ["^build"],
7      "outputs": [".next/**", "dist/**", "build/**", ".vitepress/dist/**"]
8    },
9    "dev": {
10      "cache": false,
11      "persistent": true
12    },
13    "test": {
14      "dependsOn": ["build"],
15      "outputs": ["coverage/**"]
16    },
17    "lint": {
18      "outputs": []
19    },
20    "clean": {
21      "cache": false
22    }
23  }
24}
25

配置说明

  • dependsOn: ["^build"]:构建前先构建依赖的子包
  • outputs:指定构建输出目录,用于缓存判断
  • cache: false:开发模式不缓存,避免热更新问题
  • persistent: true:开发模式持续运行(如 watch 模式)

4. 根目录 package.json 配置

1{
2  "name": "your-project-monorepo",
3  "version": "1.0.0",
4  "private": true,
5  "scripts": {
6    "build": "turbo run build",
7    "dev": "turbo run dev",
8    "test": "turbo run test",
9    "lint": "turbo run lint",
10    "clean": "turbo run clean && rm -rf node_modules",
11    "format": "prettier --write \"**/*.{ts,tsx,md,json}\""
12  },
13  "devDependencies": {
14    "turbo": "^2.0.0",
15    "prettier": "^3.0.0"
16  },
17  "packageManager": "[email protected]",
18  "engines": {
19    "node": ">=18.0.0",
20    "pnpm": ">=9.0.0"
21  }
22}
23

5. 搭建核心包

1# 创建核心包目录并初始化
2mkdir -p packages/core && cd packages/core
3pnpm init -y
4
5# 安装核心依赖(共享依赖安装到根目录)
6pnpm add -D tsup typescript vitest @types/node -w
7

核心包 package.json

1{
2  "name": "@your-org/core",
3  "version": "1.0.0",
4  "description": "核心功能包",
5  "type": "module",
6  "main": "./dist/index.cjs",
7  "module": "./dist/index.js",
8  "types": "./dist/index.d.ts",
9  "exports": {
10    ".": {
11      "import": "./dist/index.js",
12      "require": "./dist/index.cjs",
13      "types": "./dist/index.d.ts"
14    }
15  },
16  "files": ["dist"],
17  "scripts": {
18    "build": "tsup",
19    "dev": "tsup --watch",
20    "test": "vitest run",
21    "test:watch": "vitest",
22    "lint": "eslint src/**/*.ts",
23    "clean": "rm -rf dist coverage"
24  },
25  "keywords": ["core", "utils"],
26  "license": "MIT"
27}
28

核心包 tsup.config.ts

1import { defineConfig } from 'tsup';
2
3export default defineConfig({
4  entry: ['src/index.ts'],
5  format: ['esm', 'cjs'],
6  dts: true,
7  clean: true,
8  sourcemap: true,
9  minify: true,
10  splitting: false,
11});
12

核心包 src/index.ts

1export const greet = (name: string) => {
2  return `Hello, ${name}!`;
3};
4
5export const add = (a: number, b: number) => {
6  return a + b;
7};
8

6. 搭建文档站点

1# 创建文档目录并初始化
2mkdir docs && cd docs
3pnpm init -y
4
5# 安装文档依赖
6pnpm add -D vitepress @vitepress/theme-default -w
7
8# 初始化 VitePress 文档
9npx vitepress init
10

文档 package.json

1{
2  "name": "@your-org/docs",
3  "version": "1.0.0",
4  "private": true,
5  "scripts": {
6    "dev": "vitepress dev",
7    "build": "vitepress build",
8    "preview": "vitepress preview",
9    "lint": "eslint . --ext .md,.ts",
10    "clean": "rm -rf .vitepress/dist"
11  },
12  "dependencies": {
13    "@your-org/core": "workspace:*"
14  }
15}
16

在 Markdown 中可直接导入核心包,用于示例演示:

1# 快速使用
2
3```ts
4import { greet } from '@your-org/core';
5
6console.log(greet('World')); // Hello, World!

### 7\. 搭建示例项目

```bash
# 创建示例目录并初始化
mkdir -p examples/basic && cd examples/basic
pnpm init -y

# 安装依赖(使用工作区协议引用核心包)
pnpm add @your-org/core@workspace:* -w
pnpm add -D vite @vitejs/plugin-react -w

示例 package.json

1{
2  "name": "@your-org/example-basic",
3  "version": "1.0.0",
4  "private": true,
5  "type": "module",
6  "scripts": {
7    "dev": "vite",
8    "build": "vite build",
9    "preview": "vite preview",
10    "clean": "rm -rf dist"
11  },
12  "dependencies": {
13    "@your-org/core": "workspace:*"
14  }
15}
16

8. 核心命令使用

命令作用
pnpm run dev同时启动核心包监听、文档热更新、示例热更新
pnpm run build一键构建核心包(ESM/CJS + 类型)、文档静态资源、示例
pnpm run test运行所有子包的测试(核心包单元测试、示例冒烟测试)
pnpm run lint统一校验所有子包的代码规范
pnpm run clean清理所有子包的构建产物和缓存

增量构建效果示例

  • 首次执行 pnpm run build:构建所有子包(core + docs + examples)
  • 修改核心包代码后再次执行 pnpm run build:仅重建 core 和依赖它的 examples,docs 未变更则直接复用缓存,构建速度提升 50%+

过滤特定子包执行任务

1# 只构建核心包
2pnpm run build --filter=@your-org/core
3
4# 只构建文档和示例
5pnpm run build --filter=@your-org/docs --filter=@your-org/example-basic
6
7# 构建核心包及其依赖者
8pnpm run build --filter=@your-org/core...
9

9. 版本管理与发布

使用 Changeset(推荐,适合多包版本同步)

Changeset 完全支持 Turbo monorepo,可仅发布核心包(packages/core),文档和示例不发布,并支持多包版本同步:

优势

  • ✅ 专为 monorepo 设计,支持多包版本同步
  • ✅ 自动更新依赖包的版本号
  • ✅ 变更记录清晰,便于追溯

劣势

  • ❌ 需要手动记录变更(npx changeset
  • ❌ 流程相对复杂

安装与配置

1# 安装 Changeset 并初始化
2pnpm add @changesets/cli -D -w
3npx changeset init
4

修改 Changeset 配置(.changeset/config.json)

1{
2  "$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
3  "changelog": "@changesets/cli/changelog",
4  "commit": false,
5  "access": "public",
6  "baseBranch": "main",
7  "updateInternalDependencies": "patch",
8  "ignore": ["@your-org/docs", "@your-org/example-basic"]
9}
10

发布流程

1# 1. 记录核心包变更(仅选择 @your-org/core)
2npx changeset
3
4# 2. 升级版本 + 生成 CHANGELOG
5npx changeset version
6
7# 3. 构建核心包
8pnpm run build --filter=@your-org/core
9
10# 4. 发布核心包
11pnpm publish --filter=@your-org/core --access public
12

使用 release-it(适合单包发布或简单场景)

release-it 也可以用于 monorepo,但主要用于单包发布场景。

优势

  • ✅ 自动化程度高,一条命令完成发布
  • ✅ 配置灵活,支持自定义发布流程
  • ✅ 支持 GitHub Release、npm 发布等

劣势

  • ❌ 不支持多包版本同步(需要手动处理)
  • ❌ 需要为每个包单独配置或使用脚本

方式一:在子包中单独配置(推荐)

在需要发布的子包中配置 release-it:

1# 在核心包目录下
2cd packages/core
3pnpm add release-it @release-it/conventional-changelog -D
4

核心包 release-it.config.js

1module.exports = {
2  git: {
3    commitMessage: 'chore: release @your-org/core@${version}',
4    tagName: '@your-org/core@${version}',
5    requireCleanWorkingDir: false,
6    requireBranch: 'main',
7    requireCommits: true,
8  },
9  github: {
10    release: true,
11    releaseName: '@your-org/core@${version}',
12  },
13  npm: {
14    publish: true,
15    publishPath: './',
16  },
17  hooks: {
18    'before:init': ['pnpm run test'],
19    'after:bump': ['pnpm run build'],
20    'after:release': 'echo "Release @your-org/core@${version} completed!"',
21  },
22  plugins: {
23    '@release-it/conventional-changelog': {
24      preset: 'angular',
25      infile: 'CHANGELOG.md',
26    },
27  },
28};
29

核心包 package.json scripts

1{
2  "scripts": {
3    "release": "release-it",
4    "release:patch": "release-it patch",
5    "release:minor": "release-it minor",
6    "release:major": "release-it major"
7  }
8}
9

发布流程

1# 在核心包目录下
2cd packages/core
3pnpm run release
4

方式二:在根目录统一配置(适合单包发布)

在根目录配置,配合 pnpm filter 使用:

1# 在根目录安装
2pnpm add release-it @release-it/conventional-changelog -D -w
3

根目录 release-it.config.js

1module.exports = {
2  git: {
3    commitMessage: 'chore: release v${version}',
4    tagName: 'v${version}',
5    requireCleanWorkingDir: false,
6    requireBranch: 'main',
7  },
8  hooks: {
9    'before:init': ['pnpm run test --filter=@your-org/core'],
10    'after:bump': ['pnpm run build --filter=@your-org/core'],
11  },
12  plugins: {
13    '@release-it/conventional-changelog': {
14      preset: 'angular',
15      infile: 'CHANGELOG.md',
16    },
17  },
18};
19

根目录 package.json scripts

1{
2  "scripts": {
3    "release": "release-it",
4    "release:core": "cd packages/core && pnpm run release"
5  }
6}
7

Changeset vs release-it 对比

特性Changesetrelease-it
monorepo 支持⭐⭐⭐⭐⭐(专为 monorepo 设计)⭐⭐⭐(需手动配置)
多包版本同步✅ 自动同步❌ 需手动处理
自动化程度⭐⭐⭐(需手动记录变更)⭐⭐⭐⭐⭐(一条命令)
配置复杂度⭐⭐⭐⭐⭐⭐⭐
适用场景多包项目、版本同步需求单包项目、简单场景

选型建议

  • 多包项目、需要版本同步:Changeset(推荐)
  • 单包项目、追求自动化:release-it
  • 简单场景、快速发布:release-it

高级配置

Turbo 缓存优化

1. 配置远程缓存(可选)

Turbo 支持远程缓存,团队共享构建缓存:

1# 安装 Turbo 远程缓存客户端
2pnpm add turbo -D -w
3
4# 登录 Vercel(免费提供远程缓存)
5npx turbo login
6
7# 链接项目
8npx turbo link
9

2. 优化缓存配置

1{
2  "pipeline": {
3    "build": {
4      "dependsOn": ["^build"],
5      "outputs": ["dist/**"],
6      "env": ["NODE_ENV"], // 环境变量变化时重新构建
7      "inputs": ["src/**/*.ts", "tsup.config.ts"] // 指定输入文件
8    }
9  }
10}
11

CI/CD 集成

GitHub Actions 示例

创建 .github/workflows/ci.yml

1name: CI
2
3on:
4  push:
5    branches: [main]
6  pull_request:
7    branches: [main]
8
9jobs:
10  build:
11    runs-on: ubuntu-latest
12    steps:
13      - uses: actions/checkout@v4
14
15      - uses: pnpm/action-setup@v4
16        with:
17          version: 9
18
19      - uses: actions/setup-node@v4
20        with:
21          node-version: 18
22          cache: 'pnpm'
23
24      - name: Install dependencies
25        run: pnpm install
26
27      - name: Build
28        run: pnpm run build
29
30      - name: Test
31        run: pnpm run test
32
33      - name: Lint
34        run: pnpm run lint
35

依赖管理策略

1. 公共依赖提升到根目录

1# 安装公共依赖到根目录
2pnpm add -D typescript eslint prettier -w
3
4# 子包无需重复安装,直接使用
5

2. 子包间依赖使用工作区协议

1{
2  "dependencies": {
3    "@your-org/core": "workspace:*" //  正确
4    // "@your-org/core": "1.0.0"     //  错误,无法实时同步
5  }
6}
7

3. 版本统一管理

使用 .npmrc 统一配置:

1# .npmrc
2shamefully-hoist=true
3strict-peer-dependencies=false
4

最佳实践

  1. 子包命名规范:使用 scope(如 @your-org/core),避免命名冲突
  2. 依赖管理:公共依赖提升到根目录,子包间使用 workspace:* 协议
  3. 任务配置:在 turbo.json 中准确配置 outputs,确保缓存生效
  4. 版本管理:使用 Changeset 管理版本,仅发布需要发布的包
  5. 目录结构:按功能拆分(packages、docs、examples),保持清晰
  6. 避免过度拆分:子包数量控制在 5 个以内,过多会增加配置复杂度
  7. 开发体验:使用 pnpm run dev 同时启动所有子包的开发模式

常见问题

工作区相关问题

Q: 子包间依赖如何引用?

A: 使用工作区协议 workspace:*

1{
2  "dependencies": {
3    "@your-org/core": "workspace:*"
4  }
5}
6

Q: 如何安装依赖到特定子包?

A:

1# 安装到根目录
2pnpm add -D typescript -w
3
4# 安装到特定子包
5pnpm add -D vite --filter @your-org/example-basic
6
7# 安装到所有子包
8pnpm add -D eslint --filter "./packages/*"
9

Q: 如何查看所有子包?

A:

1pnpm list -r --depth=0
2

Turbo 相关问题

Q: Turbo 缓存不生效怎么办?

A:

  1. 检查 turbo.json 中的 outputs 配置是否正确
  2. 检查构建输出目录是否在 outputs 中声明
  3. 清理缓存:pnpm run clean && rm -rf .turbo

Q: 如何只构建变更的子包?

A: Turbo 默认就是增量构建,只需执行 pnpm run build,Turbo 会自动判断哪些子包需要重新构建。

Q: 如何跳过缓存强制构建?

A:

1pnpm run build --force
2

Q: 如何查看构建依赖关系?

A:

1# 查看任务依赖图
2npx turbo run build --graph
3

版本管理相关问题

Q: Changeset 如何只发布特定包?

A: 在 .changeset/config.json 中配置 ignore 字段,或在执行 npx changeset 时只选择需要发布的包。

Q: 如何自动化发布流程?

A: 使用 GitHub Actions + Changeset,参考 Changeset 文档

Q: release-it 能否用于 monorepo?

A: 可以,但主要用于单包发布场景。如果项目只有一个包需要发布,release-it 更简单;如果需要多包版本同步,建议使用 Changeset。

Q: release-it 如何发布 monorepo 中的特定包?

A:

1# 方式一:在子包目录下执行
2cd packages/core
3pnpm run release
4
5# 方式二:使用 pnpm filter
6pnpm --filter @your-org/core run release
7

性能优化相关问题

Q: 如何提升构建速度?

A:

  1. 配置 Turbo 远程缓存(团队共享)
  2. 优化 turbo.jsonoutputs 配置
  3. 使用 dependsOn 合理配置任务依赖
  4. 避免不必要的任务依赖

Q: 如何减少 node_modules 体积?

A:

  1. 使用 pnpm(默认使用符号链接,节省磁盘空间)
  2. 公共依赖提升到根目录
  3. 使用 .npmrc 配置 shamefully-hoist=false

参考资源


文档版本:v2.0
最后更新:2024 年


Monorepo 架构以及工具选型、搭建》 是转载文章,点击查看原文


相关推荐


告别 if-else:C#.NET 模式匹配让代码更优雅的正确方式
唐青枫2025/11/26

简介 模式匹配是 C# 7.0 开始引入的革命性特性,它提供了更简洁、更强大的方式来检查和提取数据中的信息。随着每个版本的更新,模式匹配功能不断强化,成为现代 C# 开发的核心特性。 模式匹配允许将输入表达式与各种特征进行匹配,支持多种模式类型。它主要用于: is 表达式:检查并可能声明变量。 switch 语句:传统分支逻辑。 switch 表达式:更简洁的表达式形式(C# 8.0 引入)。 模式匹配演进历程 版本新增特


从源码到npm:手把手带你发布Vue 3组件库
良山有风来2025/11/24

还记得上次为了统一团队UI风格,你不得不把同一个按钮组件复制粘贴到十几个项目里的痛苦经历吗?每次修改都要同步更新所有项目,一不小心就漏掉一两个,测试同事追着你满公司跑…… 今天,咱们就来彻底解决这个问题!我将带你从零开始,用最新的Vite工具链打包并发布一个专业的Vue 3组件库。学完这篇,你就能像Element Plus那样,让团队通过一句npm install就能使用你精心打造的组件库。 为什么你需要自建组件库? 先别急着写代码,咱们聊聊为什么这事值得你花时间。想象一下这些场景: 早上刚优化


Claude Code CLI更新又又又报错了?快来试试官方原生安装方式
小溪彼岸2025/11/22

前言 今天准备使用Claude Code CLI时发现Claude Code CLI又出问题不能用了,使用 npm list -g 查看NPM全局安装列表中又是有的,只是此时的CLI看着有些异常没有版本号🤣。这已经不是第一次出现这个问题了,之前就出现过,上次就是各种手动删除后重装才正常的,真是够折腾的。 本想打开官网看下Claude Code CLI的安装方式,打开官网后发现,官方发布了Claude Code CLI的原生版本安装方式,只需一行命令即可安装Claude Code CLI。 官


硬刚GPT 5.1,Grok 4.1来了,所有用户免费使用!
三寸3372025/11/20

还得是马斯克,直接杠! 就在OpenAI发布GPT-5.1没几天,马斯克这边就坐不住了。 刚刚,xAI官宣推出最新版本Grok 4.1,直接面向全球所有用户免费开放。 马斯克本人在X平台上表示,这次更新会让用户"明显感受到速度和质量的双重提升"。 目前,用户可以在Grok网站、X平台,以及iOS和Android应用程序上直接使用Grok 4.1。 更关键的是,这次不是只有付费用户才能体验,所有用户(包括免费用户)都能用上。 这波操作可谓诚意十足! 和前代Grok 4


Gemini 3.0 发布,Antigravity 掀桌,程序员何去何从?
该用户已不存在2025/11/19

昨天,谷歌不开任何发布会,直接甩出了一枚重磅炸弹——Gemini 3.0。 这一波更新来得猝不及防。Gemini 3.0 不仅第一时间登陆了 AI Studio 和 Gemini CLI,还直接渗透到了开发者最常用的工具链里:Cursor、GitHub Copilot、JetBrains 全家桶,以及 Cline。甚至连谷歌自家的一系列产品,今天起也都集成了 Gemini 3 Pro 预览版。 伴随模型发布,谷歌还掏出了一个全新的开发平台,Google Antigravity。谷歌说这是 VS


Python 的内置函数 zip
IMPYLH2025/11/17

Python 内建函数列表 > Python 的内置函数 zip Python 的内置函数 zip() 是一个非常有用的工具函数,用于将多个可迭代对象(如列表、元组等)中的元素按顺序打包成一个个元组,然后返回由这些元组组成的迭代器。其基本语法为: zip(*iterables) 其中,iterables 可以是多个可迭代对象,比如列表、元组、字符串等。zip() 函数会将这些可迭代对象中相同索引位置的元素组合成一个元组,最终返回一个迭代器。 主要特点 并行迭代:zip() 可以同时遍


Python 的内置函数 round
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 round Python 的内置函数 round() 用于对数字进行四舍五入操作。它的基本语法如下: round(number, ndigits) 其中: number 是需要进行四舍五入的数字ndigits 是保留的小数位数(可选参数) 详细说明: 当省略 ndigits 参数时,函数会返回最接近的整数ndigits 可以为负数,表示对整数部分进行四舍五入(例如十位、百位等) 应用示例: # 基本用法 print(ro


Python 的内置函数 next
IMPYLH2025/11/15

Python 内建函数列表 > Python 的内置函数 next Python 的内置函数 next() 是一个用于迭代器协议的重要函数,它能够从迭代器中获取下一个元素。next() 函数的基本语法如下: next(iterator[, default]) 其中: iterator 是一个可迭代对象(必须实现了 __next__() 方法的迭代器)default 是可选参数,当迭代器耗尽时返回该默认值,若不提供默认值且迭代器耗尽则会抛出 StopIteration 异常 使用示例:


CMake Error at fc_base/gflags-src/CMakeLists.txt:73
WGS.2025/11/14

完整日志: CMake Warning (dev) at /root/miniconda3/share/cmake-4.1/Modules/FetchContent.cmake:1373 (message): The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy CMP0135 is not set. The policy's OLD behavior will be used. When using a UR


Lua 的 Math 模块
hubenchang05152025/11/13

#Lua 的 Math 模块 请查看 Lua 标准库模块列表 了解更多相关 API。 常量说明math.huge数值的最大值,通常对应 C 语言中的 HUGE_VALmath.maxinteger整数的最大值,通常对应 C 语言中的 LONG_MAXmath.mininteger整数的最小值,通常对应 C 语言中的 LONG_MINmath.pi圆周率 函数说明math.max取最大值math.min取最小值math.ceil向上取整math.floor向下取整math.modf分解整数部

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读