前言
当我们在开发类库时,往往会在实际项目中引入开发中的类库,来调试实际使用的效果。并且最好是需要类库改变后,能够自动、实时的在项目中反馈。
npm有三种方法实现不发布npm包,就在本地像npm i安装一样去使用它,如下:
| 特性 | 工作空间(Workspaces) | 本地路径依赖 (file:) | npm link |
|---|---|---|---|
| 依赖管理方式 | 单仓库多包(monorepo) | 跨项目文件引用 | 全局符号链接 |
| 版本控制 | 由根 package.json 统一管理 | 各自维护版本,可能冲突 | 忽略版本,直接引用源码 |
| 修改传播 | 实时生效(无需重新安装) | 实时生效 | 实时生效 |
| 依赖结构 | 扁平化(共享根 node_modules) | 嵌套结构(可能导致重复安装) | 全局链接,可能与其他项目冲突 |
| 生产环境兼容性 | 完全兼容(发布独立包) | 需替换为 npm 包版本 | 不可用(必须替换为 npm 包) |
| 适用场景 | 大型项目内部模块协作 | 临时引用本地包 | 频繁开发的本地包 |
下面我们就来分别介绍它们的使用
1.前置条件
首先我们建立一个项目目录,后面的案例都按照这个目录操作
├─ app/ # app项目
│ ├─ index.js
│ └─ package.json
├─ lib1/ # sub项目
│ ├─ index.js
│ └─ package.json
1.本地路径依赖 and npm link
本地依赖开发非常简单,直接将依赖指向本地地址即可。它其实最终也是执行的npm link,相对于"scripts"项的脚本一样
// app/package.json
{
"dependencies":{
"lib-name1":"../lib1",// lib目录必须是一个npm项目
}
}
执行npm i,npm就会自动把./lib目录链接到app/node_modules下,然后像普通模块一样引入即可
// app/index.js
import m from "lib-name1";
然后我们看看npm link的使用方式,直接在app/目录的命令行中执行
app> npm link ../lib1; //在app/node_modules中的文件名由../lib1/package.json中的name项决定
你可以查看app/node_modules目录,可以看到本地路径依赖和npm link最终都是在其内部生成了一个目录链接符
2.workspace
建立一个新的目录结构
├─ app/ # app项目
| ├─ index.js
| ├─ package.json
| |
| ├─ pack1/
| | ├─ index.js
| | └─ package.json #s 引入lib1
| |
| └─ packages/
| └─ pack2/
| ├─ index.js
| └─ package.json #s 引入lib2
│
├─ pack0/
├─ index.js
└─ package.json #s 引入lib0
然后配置workspace
// app/package.json
{
"workspace":[
"../pack0",
"./pack1",
"./packages/*", // 引入./packages/目录下所有项目
]
}
workspace最终也是建立一个"npm link"目录链接,但是它与npm link和本地路径依赖不一样的是,workspace如果配置的是在当前根目录内的项目作为依赖,那么所有的依赖都是统一安装到根目录的node_module下进行复用,即便你是在依赖项中执行npm i也不会安装到workspace项目中的node_module
如果配置的workspace项目,根目录外,则无法复用。依赖项会安装到workspace项目的node_modules中。
在上面的目录结构执行完npm i之后,包安装位置结果如下
|-app/node_modules
| |- lib1
| |- lib2
|-pack0/node_modules
|- lib0
3.结论
不论是库还是单体项目,都推荐使用workspace进行包管理!