从 0 到 1 搭建 pnpm + Workspaces + Turborepo Monorepo 保姆级指南

🏗️ 从 0 到 1 搭建 pnpm + Workspaces + Turborepo Monorepo 保姆级指南

本指南面向新人,从空目录开始,手把手带你搭建一个基于 pnpm Workspaces + Turborepo 的 monorepo 项目。 最终项目结构:apps/web(Vue 3 应用)+ packages/shared(共享工具包),全程使用 TypeScript。


📋 最终项目结构预览

搭建完成后的目录结构如下:

csharp 复制代码
work/
├── package.json              # 根项目配置(定义 monorepo 入口脚本)
├── pnpm-workspace.yaml       # pnpm 工作区配置(声明子包目录)
├── turbo.json                # Turborepo 任务管道配置
├── tsconfig.base.json        # TypeScript 基础配置(供子包继承)
├── .gitignore                # Git 忽略规则
├── 搭建流程.md               # 本文档
├── apps/
│   └── web/                  # Vue 3 + Vite + TypeScript 应用
│       ├── package.json
│       ├── tsconfig.json
│       ├── vite.config.ts
│       ├── index.html
│       └── src/
│           ├── main.ts       # Vue 应用入口
│           └── App.vue       # 根组件
└── packages/
    └── shared/               # 共享工具包(@work/shared)
        ├── package.json
        ├── tsconfig.json
        └── src/
            └── index.ts      # 导出工具函数

🔧 环境准备

1. 安装 Node.js

前往 Node.js 官网 下载并安装 LTS 版本(推荐 v20 或更高)。

安装完成后,打开终端验证:

bash 复制代码
node --version
# 预期输出: v20.x.x 或更高

2. 安装 pnpm

pnpm 是一个快速、节省磁盘空间的包管理器,支持 Workspaces(工作区),是搭建 monorepo 的首选工具。

bash 复制代码
# 方式一:使用 npm 全局安装
npm install -g pnpm

# 方式二:使用 Node.js 自带的 corepack(推荐)
corepack enable
corepack prepare pnpm@latest --activate

验证安装:

bash 复制代码
pnpm --version
# 预期输出: 12.x.x 或更高

💡 为什么要用 pnpm 而不是 npm/yarn?

  • 节省磁盘空间:pnpm 使用硬链接机制,相同的包只存储一份
  • 严格的依赖管理:默认不允许访问未声明的依赖(避免幽灵依赖问题)
  • 原生 Workspaces 支持:无需额外插件即可管理 monorepo

🚀 第一步:初始化项目

1.1 创建项目目录

bash 复制代码
mkdir work
cd work

1.2 初始化 package.json

bash 复制代码
pnpm init

这会生成一个默认的 package.json。我们需要手动修改它,使其成为 monorepo 的根配置:

jsonc 复制代码
{
  "name": "work-monorepo",          // 项目名称
  "version": "0.0.0",               // 版本号
  "private": true,                  // 标记为私有,防止误发布到 npm
  "packageManager": "pnpm@12.10.1", // 指定包管理器版本(用于 corepack 自动切换)
  "scripts": {
    "dev": "turbo run dev",         // 启动所有子包的开发服务器
    "build": "turbo run build",     // 构建所有子包
    "lint": "turbo run lint"        // 代码检查所有子包
  },
  "devDependencies": {
    "turbo": "^2.3.3",              // Turborepo 构建系统
    "typescript": "^5.7.2"          // TypeScript 编译器
  }
}

关键字段说明:

字段 说明
private: true 根项目不发布到 npm,仅作为 monorepo 容器
packageManager 配合 corepack 使用,团队成员自动使用相同版本的 pnpm
scripts 所有脚本通过 turbo run 委托给 Turborepo 执行,实现任务编排和缓存
devDependencies 全局开发依赖,所有子包共享

📦 第二步:配置 pnpm Workspaces

2.1 创建 pnpm-workspace.yaml

在项目根目录创建 pnpm-workspace.yaml 文件:

yaml 复制代码
packages:
  - "apps/*"
  - "packages/*"

onlyBuiltDependencies:
  - esbuild

配置说明:

字段 说明
packages 声明工作区目录,apps/* 和 packages/* 表示这两个目录下的每个子目录都是一个独立的工作区包
onlyBuiltDependencies 允许运行构建脚本的第三方依赖列表。pnpm 出于安全考虑默认拦截依赖的 postinstall 脚本,这里显式允许 esbuild(Vite 的底层依赖)

💡 通配符规则:

  • apps/* 匹配 apps/web、apps/admin 等所有 apps 下的子目录
  • packages/* 匹配 packages/shared、packages/ui 等所有 packages 下的子目录
  • 你也可以用 apps/** 来匹配多层嵌套目录
    ⚠️ pnpm 12 重要变更: 在 pnpm 12 之前,onlyBuiltDependencies 配置写在 package.json 的 pnpm 字段中。 pnpm 12 开始,该配置已迁移到 pnpm-workspace.yaml,package.json 中的 pnpm 字段不再被读取。

2.2 创建 .gitignore

bash 复制代码
# 依赖
node_modules
.pnpm-store

# 构建产物
dist
build
*.tsbuildinfo

# Turborepo 缓存
.turbo

# 环境变量
.env
.env.*
!.env.example

# 日志
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# 编辑器
.vscode/*
!.vscode/extensions.json
.idea

# 系统文件
.DS_Store
Thumbs.db

🛠️ 第三步:安装全局开发依赖

在根目录执行以下命令,安装 Turborepo 和 TypeScript 到根项目的 devDependencies:

bash 复制代码
pnpm install

💡 为什么不用 pnpm add -Dw turbo typescript? 因为我们已经在 package.json 的 devDependencies 中声明了 turbo 和 typescript, 直接执行 pnpm install 即可安装。-Dw 参数的含义是:

  • -D:安装为开发依赖(devDependencies)
  • -w:安装到工作区根目录(workspace root)

预期输出:

diff 复制代码
Scope: all 3 workspace projects

devDependencies:
+ turbo 2.11.7
+ typescript 5.9.3

⚠️ 关于 esbuild 构建脚本警告: 安装时可能会看到 ERR_PNPM_IGNORED_BUILDS 警告,提示 esbuild 的构建脚本被忽略。 这是 pnpm 的安全特性。我们已经通过 pnpm-workspace.yaml 中的 onlyBuiltDependencies 配置解决了此问题。即使看到此警告也不影响实际使用,因为 esbuild 的二进制文件会通过 optionalDependencies 自动安装。如果警告持续出现,可以手动执行 pnpm approve-builds 来批准构建脚本。


⚡ 第四步:配置 Turborepo

4.1 创建 turbo.json

在项目根目录创建 turbo.json:

jsonc 复制代码
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],    // 先构建上游依赖包
      "outputs": ["dist/**"]      // 缓存构建产物
    },
    "dev": {
      "dependsOn": ["^build"],    // 开发前先构建依赖
      "cache": false,             // 开发服务器不缓存
      "persistent": true          // 标记为长驻进程
    },
    "lint": {
      "dependsOn": ["^build"],    // lint 前先构建依赖
      "outputs": []               // lint 无产物输出
    }
  }
}

逐字段说明:

字段 说明
$schema JSON Schema 地址,提供编辑器自动补全和校验
tasks 任务管道定义(Turborepo v2+ 推荐字段名,旧版使用 pipeline)
dependsOn: ["^build"] ^ 表示先执行上游依赖包的同名任务。例如 apps/web 的 build 会先触发 @work/shared 的 build
outputs 声明构建产物路径,Turbo 会缓存这些文件,下次构建时直接复用
cache: false 禁用缓存(开发服务器不需要缓存)
persistent: true 标记为长驻进程,Turbo 不会等待它退出

💡 Turborepo 的核心价值:

  1. 任务编排:自动按依赖拓扑顺序执行任务(先构建 shared,再构建 web)
  2. 增量构建:只重新构建发生变化的包
  3. 构建缓存:缓存构建产物,重复构建秒级完成
  4. 并行执行:无依赖关系的任务并行执行

📝 第五步:配置 TypeScript 基础配置

5.1 创建 tsconfig.base.json

在项目根目录创建 tsconfig.base.json:

jsonc 复制代码
{
  "compilerOptions": {
    "target": "ES2020",                    // 编译目标 JS 版本
    "module": "ESNext",                    // 模块系统
    "moduleResolution": "bundler",         // 模块解析策略(适配 Vite 等打包工具)
    "baseUrl": ".",                        // 路径解析基准目录
    "lib": ["ES2020", "DOM", "DOM.Iterable"], // 类型库
    "strict": true,                        // 开启所有严格类型检查
    "esModuleInterop": true,               // 兼容 CommonJS 模块的默认导入
    "skipLibCheck": true,                  // 跳过第三方库的类型检查(加快编译)
    "forceConsistentCasingInFileNames": true, // 强制文件名大小写一致
    "resolveJsonModule": true,             // 允许导入 JSON 文件
    "isolatedModules": true,               // 每个文件独立编译(适配打包工具)
    "declaration": true,                   // 生成 .d.ts 类型声明文件
    "declarationMap": true,                // 生成声明文件的 source map
    "sourceMap": true,                     // 生成 source map
    "paths": {
      "@work/*": ["packages/*/src"]        // 路径别名,@work/shared 映射到 packages/shared/src
    }
  }
}

关键配置说明:

配置项 说明
moduleResolution: "bundler" 适配现代打包工具(Vite/webpack)的模块解析策略,支持 package.json 的 exports 字段
baseUrl: "." 设置路径解析的基准目录,paths 别名依赖此配置
paths 路径别名映射,@work/shared 会解析到 packages/shared/src/index.ts
strict: true 开启严格模式,包括 null 检查、隐式 any 检查等
declaration: true 生成类型声明文件,供引用方获取类型提示

💡 为什么需要 baseUrl? paths 别名需要 baseUrl 作为基准目录来解析相对路径。 虽然 TypeScript 5.0+ 在 moduleResolution: "bundler" 模式下理论上可以不设 baseUrl, 但为了兼容性和稳定性,建议显式设置。
⚠️ 注意:此文件仅作为 base 被子包 extends,不直接参与编译,因此不设置 include/exclude。


📚 第六步:创建共享包 packages/shared

共享包是 monorepo 的核心优势之一------多个应用可以复用同一份代码。

6.1 创建目录结构

bash 复制代码
packages/shared/
├── package.json       # 包配置
├── tsconfig.json      # TypeScript 配置(继承根配置)
└── src/
    └── index.ts       # 源码入口

6.2 创建 package.json

jsonc 复制代码
{
  "name": "@work/shared",           // 包名,使用 @work scope 命名空间
  "version": "0.0.0",               // 版本号
  "private": true,                  // 私有包,不发布到 npm
  "main": "./src/index.ts",         // CommonJS 入口
  "types": "./src/index.ts",        // 类型声明入口
  "exports": {
    "types": "./src/index.ts",      // TypeScript 类型解析入口
    "default": "./src/index.ts"     // 默认入口
  },
  "scripts": {
    "build": "tsc"                  // 使用 TypeScript 编译器构建
  }
}

关键字段说明:

字段 说明
name: "@work/shared" @work 是 scope(命名空间),shared 是包名。使用 scope 可以避免与公共包冲突
exports 现代包导出配置。types 条件让 TypeScript 正确解析类型,default 条件是运行时入口
main / types 兼容旧版工具的入口配置

💡 为什么 exports 中 types 和 default 都指向 src/index.ts? 在 monorepo 内部开发时,我们直接引用源码(而非编译后的 dist), 这样可以获得更好的开发体验(无需先编译再引用,修改即时生效)。 发布到 npm 时,再修改为指向 ./dist/index.js 和 ./dist/index.d.ts。

6.3 创建 tsconfig.json

jsonc 复制代码
{
  "extends": "../../tsconfig.base.json",  // 继承根目录的基础配置
  "compilerOptions": {
    "outDir": "./dist",                   // 编译输出目录
    "rootDir": "./src"                    // 源码根目录
  },
  "include": ["src"]                      // 只编译 src 目录下的文件
}

说明:

  • extends 继承根配置,避免重复配置
  • outDir 指定编译输出目录(执行 pnpm build 时生成)
  • rootDir 指定源码根目录,确保编译后的目录结构与源码一致
  • include 限定编译范围

6.4 创建 src/index.ts

typescript 复制代码
/**
 * 格式化日期为 YYYY-MM-DD 格式
 * @param date 日期对象
 * @returns 格式化后的日期字符串
 */
export function formatDate(date: Date): string {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

/**
 * 生成问候语
 * @param name 名字
 * @returns 问候语字符串
 */
export function greet(name: string): string {
  return `你好,${name}!欢迎来到 Work Monorepo 🎉`;
}

这里导出了两个工具函数:

  • formatDate:将 Date 对象格式化为 YYYY-MM-DD 字符串
  • greet:生成问候语字符串

🌐 第七步:创建 Vue 应用 apps/web

7.1 创建目录结构

bash 复制代码
apps/web/
├── package.json       # 应用配置
├── tsconfig.json      # TypeScript 配置
├── vite.config.ts     # Vite 构建配置
├── index.html         # 入口 HTML
└── src/
    ├── main.ts        # Vue 应用入口
    └── App.vue        # 根组件

7.2 创建 package.json

jsonc 复制代码
{
  "name": "@work/web",               // 应用名
  "version": "0.0.0",
  "private": true,
  "type": "module",                  // 使用 ES Module
  "scripts": {
    "dev": "vite",                                       // 启动开发服务器
    "build": "vue-tsc --noEmit && vite build",           // 先类型检查再构建
    "preview": "vite preview"                            // 预览构建产物
  },
  "dependencies": {
    "vue": "^3.5.13",                                    // Vue 3
    "@work/shared": "workspace:*"                        // 引用本地共享包
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.2.1",                      // Vite 的 Vue 插件
    "vite": "^6.0.5",                                    // Vite 构建工具
    "typescript": "^5.7.2",                              // TypeScript
    "vue-tsc": "^2.1.10"                                 // Vue 的类型检查工具
  }
}

关键字段说明:

字段 说明
type: "module" 声明此包使用 ES Module(import/export),Vite 要求
@work/shared: "workspace:*" 核心! 使用 workspace:* 协议引用本地工作区包。pnpm 会自动创建符号链接,无需手动维护路径
build 脚本 先执行 vue-tsc --noEmit 做类型检查(不输出文件),通过后再执行 vite build 构建

💡 workspace:* 协议详解:

  • workspace:*:匹配工作区中任意版本
  • workspace:^1.0.0:匹配工作区中 >= 1.0.0 且 < 2.0.0 的版本
  • workspace:~1.0.0:匹配工作区中 >= 1.0.0 且 < 1.1.0 的版本
  • 安装后,pnpm 会在 node_modules/@work/shared 创建一个符号链接指向 packages/shared

7.3 创建 tsconfig.json

jsonc 复制代码
{
  "extends": "../../tsconfig.base.json",  // 继承根配置
  "compilerOptions": {
    "types": ["vite/client"],             // 引入 Vite 客户端类型(如 import.meta.env)
    "jsx": "preserve"                     // 保留 JSX 语法,交由 Vue 编译器处理
  },
  "include": ["src"]                      // 编译范围
}

说明:

  • types: ["vite/client"]:提供 import.meta.env 等 Vite 专用 API 的类型声明
  • jsx: "preserve":Vue 的 <script setup lang="ts"> 需要此配置

7.4 创建 vite.config.ts

typescript 复制代码
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
});

说明:

  • defineConfig:提供配置类型的辅助函数
  • vue():启用 Vue 单文件组件(.vue)支持

7.5 创建 index.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Work Web</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

说明:

  • <div id="app">:Vue 应用的挂载点
  • <script type="module" src="/src/main.ts">:Vite 的入口文件

7.6 创建 src/main.ts

typescript 复制代码
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

说明:

  • createApp(App):创建 Vue 应用实例
  • .mount('#app'):将应用挂载到 index.html 中的 #app 元素

7.7 创建 src/App.vue

vue 复制代码
<script setup lang="ts">
import { greet, formatDate } from '@work/shared';

const greeting = greet('新人');
const today = formatDate(new Date());
</script>

<template>
  <div class="container">
    <h1>🚀 Work Monorepo</h1>
    <p class="greeting">{{ greeting }}</p>
    <p class="date">今天是 {{ today }}</p>
    <p class="hint">
      本页面演示了 <code>apps/web</code> 如何引用 <code>@work/shared</code> 共享包
    </p>
  </div>
</template>

<style scoped>
.container {
  max-width: 640px;
  margin: 80px auto;
  padding: 40px;
  font-family: system-ui, -apple-system, sans-serif;
  text-align: center;
  color: #333;
}

h1 {
  font-size: 2rem;
  margin-bottom: 24px;
}

.greeting {
  font-size: 1.25rem;
  color: #42b883;
  margin-bottom: 8px;
}

.date {
  font-size: 1rem;
  color: #666;
  margin-bottom: 24px;
}

.hint {
  font-size: 0.875rem;
  color: #999;
}

code {
  background: #f5f5f5;
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'Fira Code', monospace;
}
</style>

说明:

  • <script setup lang="ts">:Vue 3 组合式 API 语法糖,自动导出
  • import { greet, formatDate } from '@work/shared':直接引用共享包的函数,就像引用 npm 包一样
  • <style scoped>:CSS 样式仅作用于当前组件

✅ 第八步:安装依赖与运行验证

8.1 安装所有依赖

在项目根目录执行:

bash 复制代码
pnpm install

预期输出:

less 复制代码
Scope: all 3 workspace projects

devDependencies:
+ turbo 2.11.7
+ typescript 5.9.3

dependencies:
+ vue 3.5.13
+ @work/shared ← linked to packages/shared

devDependencies:
+ vite 6.0.5
+ @vitejs/plugin-vue 5.2.1
+ vue-tsc 2.1.10

💡 安装后发生了什么?

  1. pnpm 读取 pnpm-workspace.yaml,识别出 3 个工作区项目(根项目 + apps/web + packages/shared)
  2. 遇到 @work/shared: "workspace:*" 时,自动在 apps/web/node_modules/@work/shared 创建符号链接指向 packages/shared
  3. 将公共依赖(typescript 等)提升到根 node_modules,减少重复安装

8.2 验证构建

bash 复制代码
pnpm build

预期输出:

sql 复制代码
$ turbo run build

 • turbo 2.11.7
 • Packages in scope: @work/shared, @work/web
 • Running build in 2 packages
 • Remote caching disabled

@work/shared:build: cache miss, executing
@work/shared:build: $ tsc

@work/web:build: cache miss, executing
@work/web:build: $ vue-tsc --noEmit && vite build
@work/web:build: vite v6.x.x building for production...
@work/web:build: transforming...
@work/web:build: ✓ 13 modules transformed.
@work/web:build: rendering chunks...
@work/web:build: computing gzip size...
@work/web:build: dist/index.html                  0.41 kB │ gzip:  0.28 kB
@work/web:build: dist/assets/index-xxx.css         0.51 kB │ gzip:  0.28 kB
@work/web:build: dist/assets/index-xxx.js         63.66 kB │ gzip: 25.54 kB
@work/web:build: ✓ built in 362ms

 Tasks:    2 successful, 2 total
Cached:    0 cached, 2 total
  Time:    2.188s

验证要点:

  • ✅ Turbo 识别出 2 个包:@work/shared 和 @work/web
  • ✅ 按依赖顺序执行:先构建 @work/shared(tsc 编译),再构建 @work/web(vue-tsc 类型检查 + vite build)
  • ✅ 两个任务全部成功

💡 Turbo 的构建顺序: 因为 apps/web 依赖 @work/shared,Turbo 会自动先构建 shared 包,再构建 web 应用。 这就是 turbo.json 中 dependsOn: ["^build"] 的作用------^ 表示上游依赖。

8.3 启动开发服务器

bash 复制代码
pnpm dev

预期输出:

scss 复制代码
$ turbo run dev

@work/shared:build: $ tsc
@work/web:dev: cache miss, executing
@work/web:dev: $ vite

  VITE v6.x.x  ready in xxx ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

打开浏览器访问 http://localhost:5173/,你应该看到:

  • 🚀 Work Monorepo 标题
  • "你好,新人!欢迎来到 Work Monorepo 🎉" 问候语
  • 当前日期

这证明 apps/web 成功引用了 @work/shared 共享包的函数!

8.4 再次构建验证缓存

停止开发服务器(Ctrl + C),再次执行构建:

bash 复制代码
pnpm build

预期输出:

yaml 复制代码
 Tasks:    2 successful, 2 total
Cached:    2 cached, 2 total    ← 注意这里变成了 2 cached
  Time:    234ms                ← 时间大幅减少

💡 Turbo 缓存生效了! 因为代码没有变化,Turbo 直接从缓存中恢复了构建产物,无需重新编译。


❓ 常见问题

Q1: workspace:* 协议是什么意思?

workspace:* 是 pnpm Workspaces 的特殊依赖协议,表示"引用本地工作区中的包,匹配任意版本"。pnpm 会在 node_modules 中创建符号链接,指向本地源码。修改共享包代码后,引用方会立即生效,无需重新安装。

Q2: 安装依赖时报 ERR_PNPM_IGNORED_BUILDS 错误怎么办?

这是 pnpm 12 的安全特性,默认拦截第三方依赖的 postinstall 脚本。解决方法:

  1. 在 pnpm-workspace.yaml 中配置 onlyBuiltDependencies(推荐):

    yaml 复制代码
    onlyBuiltDependencies:
      - esbuild
  2. 手动批准(需要在终端中操作):

    bash 复制代码
    pnpm approve-builds

注意:即使看到此警告,通常也不影响项目构建和运行,因为 esbuild 的二进制文件会通过 optionalDependencies 自动安装。

Q3: TypeScript 报"找不到模块 @work/shared"怎么办?

检查以下几点:

  1. 确认 tsconfig.base.json 中配置了 baseUrl: "." 和 paths 别名
  2. 确认 packages/shared/package.json 中 exports 字段正确配置了 types 条件
  3. 确认执行了 pnpm install,使 workspace 链接生效
  4. 尝试重启 TypeScript 语言服务(VSCode 中 Ctrl+Shift+P → "TypeScript: Restart TS Server")

Q4: 如何清除 Turborepo 缓存?

bash 复制代码
# 清除所有 Turbo 缓存
npx turbo clean

# 或者手动删除 .turbo 目录
Remove-Item -Recurse -Force .turbo    # PowerShell
rm -rf .turbo                          # bash/zsh

Q5: 如何新增一个包(如 packages/ui)?

  1. 创建目录 packages/ui
  2. 创建 packages/ui/package.json(参考 packages/shared 的格式)
  3. 创建 packages/ui/tsconfig.json(继承根配置)
  4. 创建源码文件 packages/ui/src/index.ts
  5. 在需要引用的应用中添加依赖:"@work/ui": "workspace:*"
  6. 执行 pnpm install 链接新包

pnpm-workspace.yaml 中的 packages/* 通配符会自动识别新包,无需修改配置。

Q6: pnpm 12 中 package.json 的 pnpm 字段不生效?

pnpm 12 开始,原来写在 package.json 中 pnpm 字段的配置(如 onlyBuiltDependencies、overrides 等)已迁移到 pnpm-workspace.yaml。package.json 中的 pnpm 字段不再被读取。

迁移示例:

jsonc 复制代码
// ❌ 旧方式(package.json 中,pnpm 12 不再读取)
{
  "pnpm": {
    "onlyBuiltDependencies": ["esbuild"]
  }
}

// ✅ 新方式(pnpm-workspace.yaml 中)
onlyBuiltDependencies:
  - esbuild

Q7: 多个应用如何共享配置(如 ESLint、Prettier)?

可以创建一个 packages/config 包来存放共享配置:

bash 复制代码
packages/
├── shared/          # 共享工具函数
└── config/          # 共享配置
    ├── eslint/
    │   └── index.js
    └── prettier/
        └── index.js

然后在各应用中通过 workspace:* 引用:

jsonc 复制代码
{
  "devDependencies": {
    "@work/config": "workspace:*"
  }
}

🎉 恭喜!搭建完成

你已经成功搭建了一个基于 pnpm + Workspaces + Turborepo 的 monorepo 项目!

回顾你掌握的知识点:

  • ✅ pnpm Workspaces 的工作区配置和包间引用(workspace:* 协议)
  • ✅ Turborepo 的任务编排、依赖拓扑和构建缓存
  • ✅ TypeScript 在 monorepo 中的配置继承和路径别名
  • ✅ Vue 3 + Vite 应用的搭建和共享包引用

下一步可以尝试:

  • 添加更多应用(如 apps/admin 管理后台)
  • 添加更多共享包(如 packages/ui 组件库、packages/config 配置包)
  • 集成 ESLint + Prettier 统一代码风格
  • 配置 CI/CD 流水线
  • 启用 Turborepo 远程缓存
相关推荐
智驭未来掌门人1 小时前
AI编程时代的设计系统落地指南:从分类选型到项目实战
前端
vipxieliang1 小时前
深入理解 JavaScript 数据类型与类型转换
前端·javascript
用户15741568165341 小时前
告别硬编码下拉选项:Vue 3 企业项目字典化改造实录
前端
明航咨询-陈老师1 小时前
2026信创“硬门槛“解码:国测(Ⅲ级首现/首个Ⅱ级OS) × LS(LS1-4) 双资质实操对照
前端
前端snow1 小时前
别再死磕单 Agent 了!多智能体架构 + LangGraph 实战,一篇全讲透
前端
IMPYLH1 小时前
HTML 的 <tr> 元素
前端·html
梦想平凡2 小时前
棋牌游戏技术实战(一):用 Node.js 实现房间消息队列、请求幂等与断线恢复
游戏·node.js
行者全栈架构师2 小时前
【鸿蒙心迹】ArkUI 列表性能实战——为什么 200 条数据页面掉到 20fps,LazyForEach 怎么救(HarmonyOS 7.x)
前端·算法·架构
派小心.2 小时前
热力图工具的多页面管理功能怎么比?
前端·数据分析