monorepo-不同包管理器workspace的使用方法

/post/workspace article cover image

在日益复杂的需求下,单一仓库已经不能满足团队开发的需求。多仓库聚合开发模式由此诞生,此笔记主要记录不同包管理器(npm、yarn、pnpm)下workspace的使用方式及功能

npm

npm自7.x版本以后支持workspace

package.json配置

json
{
  "name": "xxx",
  "workspaces": [
    "namespace-a",
    "namespace-b"
  ]
}

npm install之后所有包下的依赖都会被软连接 symlink 到顶层的node_modules

workspace使用

js
// namespace-a
module.exports = 'a';

// ./lib/index.js
const moduleA = require('namespace-a');
console.log(moduleA); // a

workspace相关命令行语句

shell
// 创建workspace,前提确保pakcage.json中workspaces是否配置
npm init -w ./packages/b

// 安装依赖至对应workspace
npm install xxx -w namsapce-a

// 运行指定workspace脚本
npm run dev --workspaces // 运行全部
npm run dev --workspace=namespace-a // 运行单个
npm run dev --workspace=namespace-a --workspace=namespace-b // 按次序运行多个

// 使用--if-present忽略不存在执行脚本的模块
npm run dev --workspaces --if-present

yarn

package.json配置

json
{
  "private": "true",
  "workspaces": [
    "namespace-a",
    "namespace-b"
  ]
}

<Callout>因为monorepo并不会对外暴露,所以private是必须的。</Callout>

workspace使用

json
{
  "name": "namespace-a",
  "version": "1.0.0",
  "dependencies": {
    "package-a": "1.0.0"
  }
}
json
{
  "name": "namespace-b",
  "version": "1.0.0",
  "dependencies": {
    "package-a": "1.0.0",
    "namespace-a": "1.0.0"
  }
}

当运行yarn install时,所有workspace下的子项所有依赖都会集中在根工作区的node_modules中,根据依赖关系最终结构如下:

text
/node_modules
/node-modules/package-a
/node-modules/namespace-a -> /namespace-a

workspace相关命令行语句

shell
// 执行对应子项命令
yarn workspace workspaceName commandName

// 安装依赖到指定子项
yarn workspace workspaceName add -D react

// 在所有子项上执行命令
yarn workspaces foreach commandName

// 列出所有工作区
yarn workspaces list

<Callout type="info">lerna是建立在yarn底层实现的高级功能工具,通常搭配使用</Callout>

pnpm

pnpm作为新一代包管理器,其symlink非扁平式的node_modules嵌套结构使得每一个包只会被'安装一次',使得内盘容量和开发效率大大提升

yaml
packages:
  - "apps/*"
  - "libs/*"
# - ***

影响workspace的相关配置

yaml
# 将本地包连接到node_modules
link-workspace-packages=true
# 优先使用工作目录的package,只有save-workspace-protocal=false时有效
prefer-workspace-packages=false
# 共享lock文件,有利于模块解析
shared-workspace-lockfile=true
# 用来控制依赖在package.json中的版本范围
save-workspace-protocol=true
# 递归执行是否作用在根工作区
include-workspace-root=false

workspace相关命令

shell
// 安装至根工作区的package.json
pnpm add -w -D xxx