本文主要介绍使用npm link的风险以及我们为什么使用npx link来替代它

先抛结论

使用npm install或者npx link去软连接一个本地包作为依赖而不是使用npm link

$ npx link <package-path>

npm link是hiroki osame开发的一个更安全、更可预测的npm link的替代品

因为如下原因我们应该避免使用npm link

  1. 多个Node.js版本同时使用容易出错

  2. link失败不会报错并且会回退到直接从npm仓库进行安装

  3. 会有预期之外的二进制可执行文件安装

  4. 不符合预期的软链接删除

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 linkmy-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的缺点

  • 多个Node.js版本同时使用容易出错

如果开发环境中使用类似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在无法找到要链接的本地包时也不会报错

  • link失败不会报错并且会回退到直接从npm仓库进行安装

如果尝试在一个包中执行npm link a ,就算这个包之前并没有注册为全局链接,这个命令执行也不会报错

$ npm link a
~/my-package/node_modules/a -> ~/.nvm/versions/node/v14.16.1/lib/node_modules/a

这是因为npm link的时候没有找到全局的包a,它就会从npm仓库上去全局安装这个包并创建一个软链接到这个包

只有这个包在npm远端仓库上没有这个包,npm link这个包才会失败

$ 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.

要判断链接是否真正成功,可以检查输出是否有打印两个->,注意上面的错误链接只有一个->。两个->说明创建了一个指向全局包软链接,然后链接向本地包

# npm v6
$ npm link my-linked-package
~/my-package/node_modules/my-linked-package -> ~/.nvm/versions/node/v14.16.1/lib/node_modules/my-linked-package -> ~/my-linked-package

这种检查方法只能在npm v6版本中使用。从npm v7开始,链接路径不再被输出到终端了。从下面可以发现v7开始已经不可能确定是链接本地包成功还是、安装和链接了一个包

# npm v7
$ npm link aup to date, audited 3 packages in 671msfound 0 vulnerabilities

也可以使用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中指定了binrandom-command

{"name": "my-package","bin": {"random-command": "bin.js"}
}

执行npm link就也会全局安装可执行的random-command

$ random-command
zsh: command not found: random-command$ cd my-package && npm link
added 1 package, and audited 3 packages in 548msfound 0 vulnerabilities$ random-command
Suddenly works!

全局安装也会覆盖已经存在的的全局可执行命令(取决于PATH配置–终端查找命令的环境变量)。如果使用nvm则可能会受到影响

下面的例子,覆盖了标准的Unix命令cat

$ type cat
cat is /bin/cat$ cd my-package && npm link
added 1 package, and audited 3 packages in 230msfound 0 vulnerabilities$ hash cash
$ type cat
cat is ~/.nvm/versions/node/v16.14.0/bin/cat

在包安装方面,这些风险对于包管理很普遍,从安全角度来看,这些风险并不算太高

npm link本身不是一个包安装工具。它是一个开发时进行软链接的工具。通过上文,我们了解到这种行为是会导致不少预期外的行为以及可能导致的一些错误

顺便提下上面提到的运行npm link a,则二进制执行命令a已安装到系统中。可能会认为 npm unlink a可以卸载,但它只会删除本地的软链接,而不会删除全局安装的二进制文件

卸载全局包和它的二进制执行文件需要使用:

$ npm uninstall --global a
  • 不符合预期的软链接删除

链接多个包时,将删除先前链接的包。这个行为是npm v7中引入的

以下例子pkg-a已经被链接过并且存在于node_modules中了。但当链接了第二个包pkg-b后,pkg-a就不在node_modules中了

$ 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

使用多个包进行链接时,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的可用性很差

潜在风险

As with any popular package registry, npm has a diverse collection with no standard for quality.

作为一个流行的包管理工具,npm有一个各种各样的包但却没有统一的质量标准

这里列举了一些恶意包,但这里提到的风险不仅限于攻击。当不清楚是否安装了正确的软件包时是有可能发生意外的

npm上的许多包是用来更改文件的,例如rimraf或代码linter工具。运行文件中被更改的代码可能是有可能有问题的

npm install也有可能安装错误的包,但是了解到上面提到的npm link会有一些预料之外的行为时,npm link带来的风险会更高。如下:

  • 包名称可能会发生冲突。可能使用了一个npm仓库上已有的包名字去链接本地的包。在意识到名称已被占用之前,开发和测试新的或私有包可能会遇到

  • 本地链接失败不会报错。如果被链接的包无法在本地找到,将从npm仓库下中查找。如果找到相同名称的包,则可能会意外地安装到全局

  • 二进制可执行文件被安装。如果安装了错误的包,很难发现二进制执行文件也会被全局安装并且很难意识到需要全局卸载这个二进制执行文件。这就会留下这个不符合预期的可执行文件被可能被意外执行

使用npm install作为替代

npm link的一种替代方法是使用指定包路径的npm install

$ npm install --no-save <package-path-a> <package-path-b> ...

执行这个命令会创建一个指向包的软链接而不是全局安装。这种行为就和我们使用npm link进行测试包的初衷差不多了。 加上--no-save是为了防止包的路径保存在package.json

但是npm install也是有缺点的。和npm link一样,执行npm install多次是会先移除之前的软链接。如果我们想一次链接多个包的话,必须一次将需要链接的多个包作为参数传入

$ npm install --no-save <package-path-a> <package-path-b> ...

npx link

npx link,一个小工具用来替代npm link,并且能解决上面提到的npm link的缺点

使用起来也很简单

$ npx link <package-path>

[npm link](https://github.com/privatenumber/link)不会全局安装链接的包或二进制执行文件,并且也不会删除以前的软链接,可以在不同版本的Node.js中使用。当不能解析包路径时,也会有一个执行失败报错

如果需要执行链接包的二进制文件,执行通过npx命令或者通过package scripts

4个避免使用npm link的理由相关推荐

  1. 使用npm link 创建本地模块

    1. npm link 介绍 创建一个全局的符号链接,优点是方便我们进行本地node模块的开发调用,和后期发布私服,或者npm 仓库调用是一致的以下为官方的说明:First, npm link in ...

  2. npm link run npm script

    npm link & run npm script https://blog.csdn.net/juhaotian/article/details/78672390 npm link命令可以将 ...

  3. 你所不知道的模块调试技巧 - npm link #17

    你所不知道的模块调试技巧 - npm link #17 1. 背景 node 应用开发中,我们不可避免的需要使用或拆分为 npm 模块,经常遇到的一个问题是: 新开发或修改的 npm 模块,如何在项目 ...

  4. from scapy.all import * 调试失败_记一次错:Vue-构建项目后使用 npm link 失败

    不想看过程可以直接看最后的总结 :) 起因 前天的时候就遇到了一个非常棘手的问题,在高高兴兴写完 Vue 项目后,使用 npm link 在别的项目里导入自己的包报错(这里的变量都用 xxxx 或者 ...

  5. 一文讲懂npm link

    前言 在本地开发npm模块的时候,我们可以使用npm link命令,将npm 模块链接到对应的运行项目中去,方便地对模块进行调试和测试 用法 包链接是一个两步过程: 1.为依赖项创建全局软链npm l ...

  6. npm link使用

    应用场景:   两个项目文件,一个是需要被调试的项目,一个是封装的组件项目.这里要做的是把组件项目设为全局,然后在调试项目里link再进行调试. 做法: 打开组件文件,拖到命令行里面复制路径(也有别的 ...

  7. Npm link的作用与使用

    一.为什么要用Npm link 库包在开发或迭代后,不适合发布到线上进行调试(过程繁琐且会导致版本号膨胀) 二.Npm link工作原理 `npm link` 可以帮助我们模拟包安装后的状态,它会在系 ...

  8. npm link 提示:error Error: EPERM: operation not permitted;The operation was rejected by your operating

    报错信息 解决方法 从报错信息上看,提示的是权限不足无法操作,网上找到的都是删除npmrc文件,但是没有效果,通过摸索,两种方式可以解决: 1.以管理员的身份运行vscode,然后在vscode的终端 ...

  9. npm link npm unlink

    npm link 1.在npm包中全局:npm link 2.在项目中:npm link 包名(package.json中的name) npm unlink 1.在npm包中全局:npm unlink ...

最新文章

  1. vue全家桶+Koa2开发笔记(2)--koa2
  2. Tomcat9 访问 Manager App
  3. Qt5.5.1移植到freescale imx6
  4. tcp option 结构体_基于 Kotlin 实现一个简单的 TCP 自定义协议
  5. JQUERY 常用方法汇总
  6. 提高关键词排名的28个SEO技巧
  7. hive的row_number()、rank()和dense_rank()的区别以及具体使用
  8. 百度人脸识别 人脸识别模型_当我说人脸识别很容易时,他们笑了。 但是可以。...
  9. linux中的设备名称和设备号,linux中的设备名称和设备号
  10. [转]Windows Shell 编程 第八章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987961】...
  11. 【Asp.Net Core】在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序
  12. ArrayList常用函数
  13. psm倾向得分匹配法举例_倾向得分匹配法的详细解读
  14. 文件生成BASE64,base64转文件
  15. rrt matlab算法,rrt算法matlab代码
  16. 最新xcode打包IPA----2021.1.18(完整详细图文)
  17. 卸载cad专用软件工具箱 一键安装卸载,安全可靠
  18. .Net Self Hosting 的几种方式
  19. OSX:隐藏文件或文件夹
  20. 物联网芯片型号处理器集锦资料介绍

热门文章

  1. Deployer php自动部署,基于 deployer 的 Web 端自动部署
  2. [设计模式] 设计模式面面观(3):单件模式(Singletion)-创建型模式
  3. css 绘制圆形 扇形
  4. centos 7 安装时忘记打开网络导致开机网络无法自启动解决办法
  5. EF| CodeFirst 代码先行
  6. 程序员可迁移技能的培养
  7. 无穷小微积分吁呼中俄数学中心成立!
  8. 如何查找视频文件 android,如何扫描出android手机中所有的视频文件
  9. MIUI10系统完美刷成开发版获取root超级权限的教程
  10. OpenLayers分屏联动对比