You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$ npm link non-existent-package
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/non-existent-package - Not found
npm ERR! 404
npm ERR! 404 'non-existent-package@*' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
$ random-command
zsh: command not found: random-command
$ cd my-package && npm link
added 1 package, and audited 3 packages in 548ms
found 0 vulnerabilities
$ random-command
Suddenly works!
$ type cat
cat is /bin/cat
$ cd my-package && npm link
added 1 package, and audited 3 packages in 230ms
found 0 vulnerabilities
$ hash cash
$ type cat
cat is ~/.nvm/versions/node/v16.14.0/bin/cat
$ npm link ../pkg-a
added 1 package, and audited 5 packages in 684ms
found 0 vulnerabilities
$ ls node_modules
pkg-a
$ npm link ../pkg-b
added 1 package, removed 1 package, and audited 5 packages in 703ms
found 0 vulnerabilities
$ ls node_modules
pkg-b
先抛结论
使用
npm install
或者npx link
去软连接一个本地包作为依赖而不是使用npm link
npm link是hiroki osame开发的一个更安全、更可预测的
npm link
的替代品因为如下原因我们应该避免使用
npm link
多个 Node.js 版本同时使用容易出错
link 失败不会报错并且会回退到直接从 npm 仓库进行安装
会有预期之外的二进制可执行文件安装
不符合预期的软链接删除
npm link
是什么npm link
是一个用于开发时直接将本地包链接为依赖项的一个命令行工具。通常用于发布 npm 包之前本地测试使用更多信息可查看官方文档
使用
假设存在以下模块包
my-library
: npm 包,需要在其它项目中作为依赖进行测试需要注意的是这里
my-library/package.json
中的name
属性也是应该my-library
my-application
:package/my-application
需要进行测试的项目下面演示如何将
my-application
中的my-library
链接到本地在
my-application
中执行npm link
将my-library
安装到全局。这样才能让其它本地项目有办法链接到这个包。npm link
的行为其实等同于npm install --global
$ cd ./my-library $ npm link
在
my-application
中执行npm link my-library
去链接这个包$ cd ./my-application $ npm link my-library
npm link <package-path>
也可以直接执行
npm link <package-path>
命令实现上述两步例子如下:
$ cd ./my-application $ npm link ../my-library
使用
npm link <package-path>
更加方便和不易出错,因为它是需要显式指定链接的包的路径4 个使用
npm link
的缺点如果开发环境中使用类似
nvm
的版本管理工具安装多个 Node.js 版本的话,需要确保npm link
的执行是在同一个 node 版本像上文所说,第一步执行
npm link
其实是将包安装全局。但是因为多个版本的 Node.js 的全局安装路径是互相独立的。如果在不同版本中使用,包查找会失败可以使用以下命令查看全局包的安装路径。如果 Node.js 的版本出现在打印的路径中,则全局包安装路径在不同 Node.js 版本下是独立的
$ npm root -g ~/.nvm/versions/node/v14.16.1/lib/node_modules
在不同的终端中处理多个包的时候很容易忽略不同终端下的 Node.js 版本是否一致。并且这个版本差异也很难发现,因为
npm link
在无法找到要链接的本地包时也不会报错如果尝试在一个包中执行
npm link a
,就算这个包之前并没有注册为全局链接,这个命令执行也不会报错这是因为
npm link
的时候没有找到全局的包a
,它就会从npm
仓库上去全局安装这个包并创建一个软链接到这个包只有这个包在 npm 远端仓库上没有这个包,
npm link
这个包才会失败要判断链接是否真正成功,可以检查输出是否有打印两个
->
,注意上面的错误链接只有一个->
。两个->
说明创建了一个指向全局包软链接,然后链接向本地包这种检查方法只能在 npm v6 版本中使用。从 npm v7 开始,链接路径不再被输出到终端了。从下面可以发现 v7 开始已经不可能确定是链接本地包成功还是、安装和链接了一个包
也可以使用
realpath
命令验证一个包是否链接成功$ realpath node_modules/package-name ~/my-linked-package
综上,由于缺少适当的报错,使用
npm link
带给我们不是很好的体验。特别是在多个 Node.js 版本的情况下npm link
的第一步是将包安装到全局。这个命令是由两步实现npm install --global ...可用于使二进制文件作为系统范围的 cli 命令使用。如果包有
bin
字段,通过npm link
可以另这个bin
中的命令可以直接通过终端执行命令考虑到
npm link
通常只是用来在开发中进行包的测试,全局二进制文件的安装可能会有额外的副作用。由于包可以声明具有任意名称的二进制执行文件,这种意外的副作用的影响可能非常严重下面的例子,在
package.json
中指定了bin
的random-command
执行
npm link
就也会全局安装可执行的random-command
全局安装也会覆盖已经存在的的全局可执行命令(取决于
PATH
配置--终端查找命令的环境变量)。如果使用nvm则可能会受到影响下面的例子,覆盖了标准的 Unix 命令
cat
在包安装方面,这些风险对于包管理很普遍,从安全角度来看,这些风险并不算太高
但
npm link
本身不是一个包安装工具。它是一个开发时进行软链接的工具。通过上文,我们了解到这种行为是会导致不少预期外的行为以及可能导致的一些错误顺便提下上面提到的运行
npm link a
,则二进制执行命令a
已安装到系统中。可能会认为npm unlink a
可以卸载,但它只会删除本地的软链接,而不会删除全局安装的二进制文件卸载全局包和它的二进制执行文件需要使用:
链接多个包时,将删除先前链接的包。这个行为是 npm v7 中引入的
以下例子
pkg-a
已经被链接过并且存在于node_modules
中了。但当链接了第二个包pkg-b
后,pkg-a
就不在node_modules
中了使用多个包进行链接时,
npn link
删除之前的链接包通常是不符合预期的。一般在链接第二个包之后,我们会继续运行代码并认为之前的软链接是应该不变的如果要链接多个包就必须将所有包路径一次传递给
npm link
$ npm link ../pkg-a ../pkg-b added 1 package, and audited 6 packages in 645ms found 0 vulnerabilities $ ls node_modules pkg-a pkg-b
虽然可行但这并不是一个很好的开发体验。在开发中,我们并不总是提前知道所有需要链接的包或以前链接过的包
这种令人困惑的行为说明了
npm link
的可用性很差潜在风险
作为一个流行的包管理工具,npm 有一个各种各样的包但却没有统一的质量标准
这里列举了一些恶意包,但这里提到的风险不仅限于攻击。当不清楚是否安装了正确的软件包时是有可能发生意外的
npm 上的许多包是用来更改文件的,例如rimraf或代码 linter 工具。运行文件中被更改的代码可能是有可能有问题的
npm install
也有可能安装错误的包,但是了解到上面提到的npm link
会有一些预料之外的行为时,npm link
带来的风险会更高。如下:包名称可能会发生冲突。可能使用了一个 npm 仓库上已有的包名字去链接本地的包。在意识到名称已被占用之前,开发和测试新的或私有包可能会遇到
本地链接失败不会报错。如果被链接的包无法在本地找到,将从 npm 仓库下中查找。如果找到相同名称的包,则可能会意外地安装到全局
二进制可执行文件被安装。如果安装了错误的包,很难发现二进制执行文件也会被全局安装并且很难意识到需要全局卸载这个二进制执行文件。这就会留下这个不符合预期的可执行文件被可能被意外执行
使用
npm install
作为替代npm link
的一种替代方法是使用指定包路径的npm install
执行这个命令会创建一个指向包的软链接而不是全局安装。这种行为就和我们使用
npm link
进行测试包的初衷差不多了。 加上--no-save
是为了防止包的路径保存在package.json
中但是
npm install
也是有缺点的。和npm link
一样,执行npm install
多次是会先移除之前的软链接。如果我们想一次链接多个包的话,必须一次将需要链接的多个包作为参数传入npx link
npx link
,一个小工具用来替代npm link
,并且能解决上面提到的npm link
的缺点使用起来也很简单
[npm link](https://github.com/privatenumber/link "npm link")
不会全局安装链接的包或二进制执行文件,并且也不会删除以前的软链接,可以在不同版本的 Node.js 中使用。当不能解析包路径时,也会有一个执行失败报错如果需要执行链接包的二进制文件,执行通过
npx
命令或者通过package scriptsThe text was updated successfully, but these errors were encountered: