npm link 的实现原理
上节测试 cli 的时候,通过 npm link 把这个包安装到了全局。
那 npm link 是怎么实现的呢?
答案就是软链接。
软链接类似 windows 下的快捷方式。
试一下就知道了:
cd ~/
mkdir aaa-lib
cd ./aaa-lib
echo "console.log('hello')" > test.js首先创建个目录和文件。
然后随便找一个别的目录,把 aaa-lib 目录软链过去:
cd ~/
mkdir bbb
cd bbb
ln -s ../aaa-lib ./aaa-lib打开这个目录看下:
可以看到, bbb 目录下多了 aaa-lib 这个目录。
但并不是复制,看到这个箭头了么:
这个箭头就是软链接的标记。
跑一下:
node ./aaa-lib/test.js这和复制有区别么?
当然有,复制是两份内容,而软链是同一份内容的两个引用。
改下源文件,再跑下 bbb 目录下的那份:
echo "console.log('hello2')" > ~/aaa-lib/test.js
cd ~/bbb
node ./aaa-lib/test.js可以看到,改了源文件,软链文件的内容也跟着改了。
这就是软链。
软链这种机制有非常多应用,npm link 就是用软链实现的。
之前在项目目录下执行了 npm link,其实就是把这个包注册到了全局仓库。
但用的是软链的方式。
不信看下:
首先找下全局仓库的位置:
npm get prefix当然,你的可能和我的不一样。
然后进入 lib/node_modules 目录,就是全局包的安装目录。
ls "$(npm get prefix)/lib/node_modules"可以看到,这个 my-nest-cli 就是是上节全局安装的包。
进入 bin 目录,就是全局命令的目录。
open "$(npm get prefix)/bin"其中,可以看到 my-nest-cli 注册的 my-cli 这个命令。
可以跳回原位置:
也就是说全局安装包的时候做了两件事:
- 往 npm get prefix 下的 lib/node_modules 安装了这个包
- 往 npm get prefix 下的 bin 里放了这个包里注册的命令
这样会把这个 bin 目录加到环境变量 $PATH 里。
自然就可以直接调用这些全局命令了。
其实你本地 npm install 的时候也差不多:
首先在 node_modules 下安装这个 npm 包
然后在 node_modules/.bin 下放这个包注册的命令
和全局安装的流程一样,只是位置不同。
npm link 的实现也是这两步。
先从全局仓库把 my-nest-cli 删除。
npm uninstall -g my-nest-cli再看下那两个目录:
ls "$(npm get prefix)/lib/node_modules"
ls "$(npm get prefix)/bin"确实都没 my-nest-cli 了。
然后进入上节的项目目录,执行 npm link:
npm link再看下这两个目录:
open "$(npm get prefix)/lib/node_modules"
open "$(npm get prefix)/bin"看到这个箭头标记了么,说明这个 my-nest-cli 是 link 过去的。
看下原位置:
这就是你执行 npm link 的那个目录位置。
然后 bin 下的这个 my-cli 的命令,也是从项目目录 link 过来的:
所以说,npm link 会做两件事:
- 往 npm get prefix 下的 lib/node_modules 安装了这个包(用 ln -s 创建的软链)
- 往 npm get prefix 下的 bin 里放了这个包里注册的命令(用 ln -s 创建的软链)
用起来和 npm install -g 的包的命令没区别。
删除自然也是用 npm uninstall -g xxx 来删,删除软链不影响源文件。
所以说,npm link 就是用软链模拟了 npm install -g。
此外,npm link 还有一个作用。
创建个项目:
mkdir tmp-project
cd tmp-project
npm init -y进入项目,执行
npm link my-nest-cli打印和 npm install 一样,提示添加了一个包。
看下 node_modules:
看到这个软链没,它是从哪 link 过来的呢?
从全局仓库 link 过来的。
还有 .bin 下的命令:
也是从全局仓库 link 过来的:
画个图就清楚了:
npm link 的原理是这样的:
npm link xxx 的原理是这样的:
总结
上节通过 npm link 来把项目安装到了全局,并且注册了全局命令。
用起来很方便。
这节探究了下实现原理。
原理就是软链接。
npm link 会做两件事:
- 在 npm get prefix 下的 lib/node_modules 安装了这个包(用 ln -s 创建的软链)
- 在 npm get prefix 下的 bin 里放了这个包里注册的命令(用 ln -s 创建的软链)
而 npm link xxx 则是再把这个包 link 到项目的 node_modules 下,并且把命令 link 到项目的 node_modules/.bin 下。
其实和 npm install 一样,就是用软链模拟的 npm install 的过程。
所以删除自然也是用 npm uninstall
软链在 node 生态里有很多应用,之后会继续探究。