pnpm workspace 管理 monorepo 项目实战指南

作者:知秋

时间:2026-10-31

浏览:570

本文详细记录了使用 pnpm workspace 方案管理 monorepo 项目的完整流程。从创建 workspace 配置文件、规划 packages 与 apps 目录结构,到配置 package.json 中的内部包引用,再到安装依赖及构建入口文件,逐步演示如何高效解决多项目间代码复用与依赖冲突问题,实现统一版本管理与便捷调用。

文章目录

monorepo

本文记录了采用 monorepo 架构及 pnpm workspace 工具进行项目管理的实际操作过程。

monorepo

首先需要明确使用 monorepo 的核心动机。对于负责公司内部多个项目的开发团队而言,除了各业务模块独立运行外,诸如系统管理、中间件库及通用工具等模块往往被多个项目共享。

在开发过程中,若需对共享模块进行新增或修改,为确保各项目间的一致性,传统做法往往涉及大量的复制粘贴操作。这一过程不仅繁琐低效,还极易引发依赖版本冲突或错误。

为解决上述痛点,在对比了 learn+yarn / npm 等多种方案后,最终选定 pnpm workspace 作为项目管理的核心方案。

下文将通过一个具体示例,逐步演示如何初步掌握 pnpm workspace 的配置与使用。

选择一个合适目录,创建 workspace 项目根文件夹。

D: && cd project/monorepo
mkdir demo2 && cd demo2

在项目根目录新建 pnpm-workspace.yaml 文件,并填入相应配置以启用 workspace 功能。

packages:
  - packages/*
  - apps/*
  - demo

配置文件的 packages 字段定义了 workspace 的范围,该 workspace 由指定的子项目组成;其中带有 - 前缀的字符串表示项目目录路径,具体语法细节可参考 pnpm 官方文档。

完善项目目录结构及包配置信息。

此时项目根目录仅包含一个 pnpm-workspace.yaml 文件,接下来需手动创建相关的文件夹及配置文件。

新建必要的目录结构。

mkdir packages && cd packages
mkdir components utils hooks space-play
cd .. && mkdir apps && cd apps && mkdir play1

为各个文件夹创建对应的 package.json 文件以定义包元数据。

// ./package.json
{
    "description": "A pnpm workspace example."
}
// ./packages/components/package.json
{
    "name": "@space-play/components",
    "version": "0.0.1"
}
// ./packages/utils/package.json
{
    "name": "@space-play/utils",
    "version": "0.0.1"
}
// ./packages/hooks/package.json
{
    "name": "@space-play/hooks",
    "version": "0.0.1"
}
// ./packages/space-play/package.json
{
    "name": "space-play",
    "version": "0.0.1"
}
// ./apps/play1/package.json
{
    "name": "play1",
    "version": "0.0.1"
}

观察上述配置可知,packages 目录下的 space-play 包其 package.json 文件中的命名与其他目录不同,其他包的 name 字段均带有 @space-play 前缀。这表示这些包在发布到 npm 时的安装名称,同时也表明它们均归属于 npm 命名空间下的 space-play 包体系。

此时项目的目录结构大致如下:

demo2
|    apps
|        play1
|            package.json
|    packages
|        components
|            package.json
|        hooks
|            package.json
|        utils
|            package.json
|        space-play
|            package.json
|    pnpm-workspace.yaml
|    package.json

一个基础的 monorepo 项目结构已搭建完毕,通过相关的 pnpm add 命令,即可实现本地内部包的相互调用。

例如我们想要在 apps/play1 包里调用所有的本地包,可以先在 space-play 包里安装其它本地包,再安装该包行。

具体操作示例如下:

在 workspace 环境中查找 packages/space-play,并在该包内安装 @space-play/components @space-play/hooks @space-play/utils 等依赖。

pnpm -r --filter ./packages/space-play add @space-play/components @space-play/hooks @space-play/utils

在 space-play 包中新建 index.ts 文件,用于统一导出所有依赖包。

// packages/space-play/index.ts
import type { App } from 'vue'
export * from '@space-play/components'
export * from '@space-play/hooks'
export * from '@space-play/utils'
export default {
    install(app: App) {
        console.log('已使用 space-play 包,但该包里什么都没有')
    },
    version: '0.0.1' // 这里只是作为示例,实际应该获取 package.json 里的版本
}

随后在 apps/play1 应用中引入并使用 space-play 包。

pnpm -r --filter ./apps/play1 add space-play

在 apps/play1 目录下构建一个简单的项目结构,并安装相关依赖。

demo1/apps/play1
|    app.vue
|    index.html
|    index.ts
|    package.json
|    vite.config.ts

可以看到,该项目使用了 vue、vite 这两个核心依赖,由于它们在 monorepo 的其他项目包中均有使用,因此选择在根目录统一安装,同时安装 vite 以解析 vue 文件。

pnpm add -w vue
pnpm add -w -D vite @vitejs/plugin-vue

此处执行了两条命令,且第二条命令中额外添加了 -D 参数。这是因为 vite 在编译后无需保留,而 vue 是运行所必需的,故分别将前者设为开发依赖,后者设为生产依赖。

打开 ./apps/play1/package.json 配置文件,对其添加必要内容,此处仅展示新增部分,后续配置同理。

{
    ...,
    "scripts": {
        "dev": "vite"
    }
}

文件 app.vue 和 index.html 的内容配置。

<!-- app.vue -->
<template>
  <div>打开了 app.vue</div>
</template>

<!-- index.html -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./index.ts"></script>
  </body>
</html>

文件 apps/play1/index.ts 的配置与普通 vue 项目的 main.ts 入口文件基本一致。

import { createApp } from 'vue'
import SpacePlay from 'space-play'
import App from './app.vue'
createApp(App).use(SpacePlay).mount('#app')

文件 apps/play1/vite.config.ts 的配置与普通 vue 项目的 main.ts 构建配置基本一致。

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
  plugins: [vue()],
});

至此,一个基于 pnpm workspace 的 monorepo 项目主体已基本完成,后续工作仅需填充具体业务逻辑。

注意!当前项目尚无法直接运行,因为在 packages/components、packages/hooks 及 packages/utils 目录下尚未新建 index.ts 文件,且未在这些目录下的 package.json 中配置 main 入口字段。

若在上述过程中已发现此问题并手动创建及配置了入口文件,则完成根目录的 scripts 脚本配置后即可运行项目以验证效果。

{
    ...,
    "scripts": {
        "play1": "pnpm -C apps/play1 dev"
    }
}
pnpm run play1
 ?  Local:   http://localhost:5173/

通过浏览器打开应用,可看到页面显示符合预期的内容。

monorepo

pnpm workspace - 传送门

以上就是 pnpm workspace 管理 monorepo 项目使用过程详解的详细内容,更多关于 pnpm workspace 管理 monorepo 的资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章