主流包管理工具npm、yarn、cnpm、pnpm之间的区别与联系——原理篇
接触 node 之后,一直使用npm包管理工具, cnpm 一开始会用一些,但是并没有觉得比 npm 快得多,使用 cnpm 的时候还经常安装不成功,只能再用 npm 安装一遍,渐渐的就弃用了 cnpm 。
最近在看《MongoDB高级技术栈全覆盖前端 Vue+Node+MongoDB高级全栈开发》课程,才知道还有其他包管理工具,借此机会,好好的整理一下各个包管理工具之间的区别和联系。
NPM
npm 是 Node.js 能够如此成功的主要原因之一。npm 团队做了很多的工作,以确保 npm 保持向后兼容,并在不同的环境中保持一致。
npm是围绕着 语义版本控制(semver)的思想而设计。
给定一个版本号:主版本号.次版本号.补丁版本号, 以下这三种情况需要增加相应的版本号:
- 主版本号: 当API发生改变,并与之前的版本不兼容的时候
- 次版本号: 当增加了功能,但是向后兼容的时候
- 补丁版本号:当做了向后兼容的缺陷修复的时候
npm使用一个名为package.json的文件,用户可以通过npm install --save命令把项目里所有的依赖项保存在这个文件里。
例如,运行npm install --save lodash会将以下几行添加到package.json文件中。
- "dependencies": {
- "lodash": "^4.17.4"
- }
解析,
^字符,告诉npm,安装主版本等于4的任意一个版本即可- 现在运行npm进行安装,npm将安装lodash的主版本为4的最新版,可能是 lodash@4.25.5(@是npm约定用来确定包名的指定版本的)
- 理论上,次版本号的变化并不会影响向后兼容性。因此,安装最新版的依赖库应该是能正常工作的,而且能引入自4.17.4版本以后的重要错误和安全方面的修复。
- 但是,即使不同的开发人员使用了相同的
package.json文件,在他们自己的机器上也可能会安装同一个库的不同种版本,这样就会存在潜在的难以调试的错误和“在我的电脑上…”的情形。
大多数npm库都严重依赖于其他npm库,这会导致嵌套依赖关系,并增加无法匹配相应版本的几率。
虽然可以通过npm config set save-exact true命令关闭在版本号前面使用^的默认行为,但这个只会影响顶级依赖关系。由于每个依赖的库都有自己的package.json文件,而在它们自己的依赖关系前面可能会有^符号,所以无法通过package.json文件为嵌套依赖的内容提供保证。
为了解决这个问题,npm提供了shrinkwrap命令。此命令将生成一个npm-shrinkwrap.json文件,为所有库和所有嵌套依赖的库记录确切的版本。
然而,即使存在npm-shrinkwrap.json这个文件,npm也只会锁定库的版本,而不是库的内容。即便npm现在也能阻止用户多次重复发布库的同一版本,但是npm管理员仍然具有强制更新某些库的权力。
这是引用自shrinkwrap文档的内容:
如果你希望锁定包中的特定字节,比如是为了保证能正确地重新部署或构建,那么你应该在源代码控制中检查依赖关系,或者采取一些其他的机制来校验内容,而不是靠校验版本。
npm 2会安装每一个包所依赖的所有依赖项。如果我们有这么一个项目,它依赖项目A,项目A依赖项目B,项目B依赖项目C,那么依赖树将如下所示:
- node_modules
- - package-A
- -- node_modules
- --- package-B
- ----- node_modules
- ------ package-C
- -------- some-really-really-really-long-file-name-in-package-c.js
这个结构可能会很长。这对于基于Unix的操作系统来说只不过是一个小烦恼,但对于Windows来说却是个破坏性的东西,因为有很多程序无法处理超过260个字符的文件路径名。
npm 3采用了扁平依赖关系树来解决这个问题,所以我们的3个项目结构现在看起来如下所示:
- node_modules
- - package-A
- - package-B
- - package-C
- -- some-file-name-in-package-c.js
这样,一个原来很长的文件路径名就从./node_modules/package-A/node_modules/package-B/node-modules/some-file-name-in-package-c.js变成了/node_modules/some-file-name-in-package-c.js。
这种方法的缺点是,npm必须首先遍历所有的项目依赖关系,然后再决定如何生成扁平的node_modules目录结构。npm必须为所有使用到的模块构建一个完整的依赖关系树,这是一个耗时的操作,是npm安装速度慢的一个很重要的原因。
想当然的以为每次运行npm install命令时,NPM都得从互联网上下载所有内容。
但是,npm是有本地缓存的,它保存了已经下载的每个版本的压缩包。本地缓存的内容可以通过npm cache ls命令进行查看。本地缓存的设计有助于减少安装时间。
总而言之,npm是一个成熟、稳定、并且有趣的包管理器。
cnpm
- cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm。
- npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,如果npm的服务器在中国就好了,于是淘宝团队干了这事。来自官网:“这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。”
- 官方地址:http://npm.taobao.org
- 安装:$ npm install -g cnpm --registry=https://registry.npm.taobao.org
Yarn
Yarn发布于2016年10月,截至当前2018年7月,在Github上拥有了32.2k个Star。而npm只有16.8k个Start。这个项目由一些高级开发人员维护,包括了Sebastian McKenzie(Babel.js)和Yehuda Katz(Ember.js、Rust、Bundler等)。
Yarn一开始的主要目标是解决上一节中描述的由于语义版本控制而导致的npm安装的不确定性问题。虽然可以使用npm shrinkwrap来实现可预测的依赖关系树,但它并不是默认选项,而是取决于所有的开发人员知道并且启用这个选项。
Yarn采取了不同的做法。每个yarn安装都会生成一个类似于npm-shrinkwrap.json的yarn.lock文件,而且它是默认创建的。除了常规信息之外,yarn.lock文件还包含要安装的内容的校验和,以确保使用的库的版本相同。
yarn是经过重新设计的崭新的npm客户端,它能让开发人员并行处理所有必须的操作,并添加了一些其他改进。
- 运行速度得到了显著的提升,整个安装时间也变得更少
- 像npm一样,yarn使用本地缓存。与npm不同的是,yarn无需互联网连接就能安装本地缓存的依赖项,它提供了离线模式。这个功能在2012年的npm项目中就被提出来过,但一直没有实现。
- 允许合并项目中使用到的所有的包的许可证
通常情况下不建议通过npm进行安装。npm安装是非确定性的,程序包没有签名,并且npm除了做了基本的SHA1哈希之外不执行任何完整性检查,这给安装系统程序带来了安全风险。
npm install -g yarn
强烈建议你通过最适合于你的操作系统的安装方法来安装yarn,进官网下载对应版本
yarn官方地址:https://yarnpkg.com/zh-Hans/ 点击打开链接

pnpm
可阅读pnpm的作者Zoltan Kochan发表的“为什么要用pnpm?”
- pnpm运行起来非常的快,超过了npm和yarn
- pnpm采用了一种巧妙的方法,利用硬链接和符号链接来避免复制所有本地缓存源文件,这是yarn的最大的性能弱点之一
- 使用链接并不容易,会带来一堆问题需要考虑。
- pnpm继承了yarn的所有优点,包括离线模式和确定性安装
总结
- npm仍然提供了一个非常有用的解决方案,支持大量的测试用例。大多数开发人员使用原始npm客户端仍然可以做得很好
- yarn的确定性安装,可以避免很多潜在的问题,相对安全
- pnpm可能是一些测试用例的更好的选择。例如,它可以在运行大量集成测试并希望尽可能快地安装依赖关系的中小型团队中发挥作用
与君共勉:再牛逼的梦想,也抵不住傻逼般的坚持!
主流包管理工具npm、yarn、cnpm、pnpm之间的区别与联系——原理篇的更多相关文章
- node.js开发 npm包管理工具 npm 和 cnpm区别
npm 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用. 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用 np ...
- 一文看懂npm、yarn、pnpm之间的区别
文作者对比了当前主流的包管理工具npm.yarn.pnpm之间的区别,并提出了合适的使用建议,以下为译文: NPM npm是Node.js能够如此成功的主要原因之一.npm团队做了很多的工作,以确保n ...
- [转] 一文看懂npm、yarn、pnpm之间的区别
[From] http://geek.csdn.net/news/detail/197339 原文:Understanding differences between npm, yarn and pn ...
- node的包管理工具:yarn和npm
arn是Facebook发布的一款依赖管理工具,它比npm更快.更高效. NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题. 一.yarn官方网站: 英文官网:ht ...
- 【前端】NodeJs包管理工具NPM
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS部署上的很多问题. 测试是否安装成功,出现版本提示表示安装成功. npm -v NPM常用命令 官方文档:https://www.npm ...
- NodeJS包管理工具——npm入门
如今每个语言体系中都有一个包管理工具,PHP的Composer,Ruby的gem,Python的pip,Java的Maven……当然还有Node.js的npm.有的人会奇怪为何要引入又一个新东西来让我 ...
- nodejs的包管理器npm和cnpm
http://www.ydcss.com/archives/18 3.npm介绍 3.1.说明:npm(node package manager)nodejs的包管理器,用于node插件管理(包括安装 ...
- 更换包管理工具npm为yarn
官网:https://yarnpkg.com/zh-Hans/ 主要考虑: 1. npm管理安装模块依赖的版本不太方便,容易在删除node_modules重新install或在其他机器上新安装时, 安 ...
- JavaScript 包管理工具npm 和yarn 对比
随机推荐
- 第二天:python数据类型及常用方法
数字类型 #1. 整型 a1 = 10 a2 = int(20) #2. 长整型(py2特有,py3废弃) b1 = 12345678901234567890 b2 = long(100) #3. 浮 ...
- fio安装使用
# wget http://brick.kernel.dk/snaps/fio-2.2.5.tar.gz # tar xvf fio-2.2.5.tar.gz# cd fio-2.2.5# ./con ...
- jenkins 设置中文显示
这里使用的方法是安装中文语言包,安装的插件名称是:Localization: Chinese (Simplified) 1.在插件管理,搜索 Localization: Chinese (Simpli ...
- 移动端真机debug调试神器 vConsole学习(一)之基础
参考 使用方法 移动端真机debug调试神器 vConsole的引入说明(原生态与WebPack) 移动端使用vconsole调试console vConsole ——开源的前端 console 调试 ...
- centos7安装nginx服务
Nginx发音引擎x是一个免费的开源高性能HTTP和反向代理服务器,负责处理互联网上一些最大的网站的负载. 本教程将教你如何在你的CentOS Linux 7.5机器上安装和管理Nginx. 安装Ng ...
- linux(centos7) 查看磁盘空间大小
命令: df -hl 1 显示: 文件系统 容量 已用 可用 已用% 挂载点 Filesystem Size Used Avail Use% Mounted on /dev/hda2 45G 19G ...
- vue+axios请求头封装
import { mapMutations } from 'vuex' import axios from 'axios' import { Toast } from 'mint-ui'; impor ...
- 经典i++和++i问题(附带运算符优先级问题)
转自 https://blog.csdn.net/mustard1020/article/details/79617865 1.i++和++i的区别 (1)i++简单来说就是先用i的值来参加表 ...
- odoo xml中添加数据的数字代表含义
参考原文:https://alanhou.org/odoo12-import-export-data/ <?xml version="1.0"?> <odoo n ...
- 静态static最基础的知识
static静态: 常见修饰的内容: 1.变量: 修饰变量时,叫静态变量或类变量.此变量为类所有随着虚拟机加载类是而加载入方法区,此静态变量为该类所有对象共享,在内存中只有一个副本,它 当且仅当 类的 ...