npm link 是什么
我们在开发一个npm包的过程中,一般需要在另一个项目里先测试该包的功能是否达到预期。
但我们不太可能每次一改好代码就执行 npm publish 发布到 npm 仓库,所以 npm 给我们提供了 npm-link 这个命令来进行本地化开发调试。
它允许你将本地npm包链接到另一个项目,使得你可以在不发布到npm仓库的情况下,直接在其他项目中使用你的本地包。
背后原理
为方便表述,后文均假设你开发的包名为:js-tracker
,需要使用的项目目录为 /examples
。
在你 my-pkg 的根目录通过 npm link 将该包注册为全局npm包,相当于你使用 npm install xxx -g。
但是js-tracker这个包跟其他全局npm包长得不太一样(如上图),它其实只是一个软连接(如下图),指向的其实是你刚执行npm link命令的目录。
在你需要使用js-tracker包的项目目录 /examples 执行 npm link js-tracker,相当于在 /examples/node_modules 目录中创建一个符号链接,软链接到全局npm目录中的js-tracker包。
基本用法
- 在你本地js-tracker包的根目录运行:
bash
npm link
这会在全局的npm目录中创建一个符号链接,指向你的本地包。每次更新完你js-tracker包,都需要在包的根目录重新执行 npm link。
如果还没有生效,重启vscode 试试。
- 在需要使用这个本地包的项目根目录(/examples)运行:
bash
npm link [package-name]
这里的package-name
是你的npm包名,相当于刚我们说的js-tracker。
成功执行这两条命令,你就可以在 /examples 项目中直接使用你本地的js-tracker包来进行调试了。
当你对本地包做了更改后,只需在js-tracker包的根目录中运行一下npm link
,/examples 项目中的包将自动更新,非常方便。
使用的注意点
虽然使用npm link并不难,主要是些理解成本,但还是有一些问题需要注意。
1. 不需要在package.json中填写相应的依赖项
你使用本地包的目录 /examples,无需在package.json中添加你本地调试包(js-tracker)的任何依赖。
因为前面原理中讲到了,你本地调试的包通过npm link其实已经是作为全局npm包了,所以无需你在自己项目去指定npm局部依赖。
如果你项目已经使用该包的依赖项来安装了,会运行报错,操作方法是:
- 删除package.json的有关你包的依赖项
- 删除node_modules文件夹
- 执行
npm link [your-package]
- 最后再执行
npm i
来安装你的项目npm依赖
2. npm link异常报错
这个错误点击npm的错误日志进去看提示是操作权限不足,但实际上删除掉node_modules文件夹后,错误就解决了。
3. 本地调试发现 /lib/index.js 中没有抛出default变量
打包后正常发npm包引用没有问题,但是通过npm link的方式软链接引用我们npm包就报错如下:
仔细分析/lib/index.js,发现里面确实没有default导出。但改成import Tracker from "js-tracker/lib/index.mjs";
就可以正常运行,说明很有可能我们指定的包入口文件不对。
经尝试,将我们包package.json指定的默认入口文件去掉文件后缀名即可正常运行。
因为去掉了后缀名,ESM的用法会自动去去找符合条件的mjs文件(/lib/index.mjs)。有兴趣的同学可以了解下ESM和CommonJs规范的区别。
还有一种方法,可以通过设置module字段来指定ESM方式所引用的入口文件:
json
// package.json
{
// ...
"module": "lib/index.mjs",
}
4. 调试完记得解除 link
调试完你要调试的 npm 包后,记得及时解除全局 link 软连接,不然后面你的包发上线了,你本地都获取不到最新的npm包代码。
解除方法是,在你的npm包目录(/js-tracker)执行:
bash
npm unlink [package-name]
本地调试npm包的其他方式
除了npm link,本地调试npm包还有其他两种常见方式:
- npm install path/to/my-package (传送门)
- 指定工作区间 workspaces
第1种其实比较好理解,就是npm安装的时候将你包的全路径(相对路径)给带上。
第2种是npm7以上才支持的workspaces特性,通过指定npm工作区间这种方式来实现调试本地npm包。
个人认为,第2种在前端工程化的角度上会显得更加合理,也会省去需要npm link,然后再npm unlink的麻烦。
这块内容后续等我实践完再另开一篇内容分享(先种个草)。
npm link 官方文档:docs.npmjs.com/cli/v10/com...