一、版本

yarn 最先用 workspaces 实现了 monorepo,而 npm 则要在 7.x 版本后才可以使用

1
2
3
"engines": {
"npm": ">= 7.0.0"
}

二、workspaces

新建文件夹,搭建目录结构如下:

1
2
3
4
.
├── package.json
└── package1
└── package.json

根目录的package.json配置

1
2
3
4
5
6
7
{
"name": "monorepo-demo",
"workspaces": [
"package1" // "packages/*" 以目录为单位
],
...
}

workspaces 指定要包含的子项目。如果是packages/a, packages/b, ...这种多个包的,可以使用packages/*。上面这个例子如果在根目录执行npm install后,得到的目录结构如下:

1
2
3
4
5
6
7
.
├── node_modules
│ └── package1 -> ../package1
├── package-lock.json
├── package.json
└── package1
└── package.json

可以看到,文件夹package1 会被符号链接到根目录的node_modules 文件夹下。对于包的使用和查找,和正常安装这个包并无差别。

注意:最好将子目录的 private 设置为 true,防止误发布。

新增子项目

1
npm init -w ./packages/a

调用上述命令后会自动在对应路径下新增子目录,并同步到根目录的 workspaces 中

三、批量运行子目录命令

若子目录 package.json 如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// packages/package-a/package.json
{
"name": "package-a",
"scripts": {
"build": "webpack"
}
// ...
}

// packages/package-b/package.json
{
"name": "package-b",
"scripts": {
"build": "webpack"
}
// ...
}

都有 build 命令,此时就可以使用如下命令,批量运行 build

1
2
3
4
5
6
7
8
# 批量运行
npm run build --workspaces

# 缩写方式
npm run build -ws

# 指定特定项目运行
npm run build --workspaces=a

四、总结

综上,npm 7.x 版本提供了workspaces配置,当我们在其中配置了相关子目录后,npm install时,子目录就会被符号链接到根目录的node_modules中,这样就像是我们在根目录装了一个npm link的三方包。

需要注意的是,如果是想搞个小的 monorepo 项目,可以直接使用 npm workspaces,但是如果是大型项目,涉及到子项目的依赖控制和发布,npm workspaces 可能就显得捉襟见肘,此时需要借助 lerna 这类的工具库。