【Web技术】334- yarn、npm、cnpm 三者如何优雅的在一块儿使用 ?

前端得包管理你有过几个?前端

640?wx_fmt=jpeg

一位用很差包管理器的前端,是一个入门级前端,一个用很差webpack的前端,是一个初级前端node

三个包管理器是能够一块儿用的,只要你够胆大心细,就没任何问题!webpack

javeScript编写中, 咱们尽可能不要定义全局变量,封装函数尽可能不要有反作用, 由于所有变量的查询时间会比局部变量的查询慢, 更是考虑在 Node 的环境中没法被垃圾回收的问题程序员

老规矩 先看原理

npm

  • npm 是 Node.js 可以如此成功的主要缘由之一。npm 团队作了不少的工做,以确保 npm 保持向后兼容,并在不一样的环境中保持一致。web

  • npm 是围绕着 语义版本控制(semver)的思想而设计。算法

  • 给定一个版本号:主版本号. 次版本号. 补丁版本号, 如下这三种状况须要增长相应的版本号:npm

  • 主版本号:当 API 发生改变,并与以前的版本不兼容的时候json

  • 次版本号:当增长了功能,可是向后兼容的时候segmentfault

  • 补丁版本号:当作了向后兼容的缺陷修复的时候设计模式

  • npm 2 会安装每个包所依赖的全部依赖项。若是咱们有这么一个项目,它依赖项目 A,项目 A 依赖项目 B,项目 B 依赖项目 C,那么依赖树将以下所示:

640?wx_fmt=png
  • 这个结构可能会很长。这对于基于 Unix 的操做系统来讲只不过是一个小烦恼,但对于 Windows 来讲倒是个破坏性的东西,由于有不少程序没法处理超过 260 个字符的文件路径名。

  • npm 3采用了扁平依赖关系树来解决这个问题,因此咱们的 3 个项目结构如今看起来以下所示:

存了已经下载的每一个版本的压缩包。本地缓存的内容能够经过 npm cache ls 命令进行查看。本地缓存的设计有助于减小安装时间。

640?wx_fmt=png
  • 这样,一个原来很长的文件路径名就从./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命令进行查看。本地缓存的设计有助于减小安装时间。

cnpm

  • cnpmnpm用法彻底一致,只是在执行命令时将npm改成cnpm

  • npm安装插件是从国外服务器下载,受网络影响大,可能出现异常,若是 npm 的服务器在中国就行了,因而淘宝团队干了这事。来自官网:“这是一个完整 npmjs.org 镜像,你能够用此代替官方版本 (只读),同步频率目前为 10 分钟 一次以保证尽可能与官方服务同步。

  • 官方地址:http://npm.taobao.org

  • 安装: npm install -g cnpm --registry=https://registry.npm.taobao.org

Yarn

  • Yarn一开始的主要目标是解决上一节中描述的因为语义版本控制而致使的 npm 安装的不肯定性问题。虽然可使用npm shrinkwrap来实现可预测的依赖关系树,但它并非默认选项,而是取决于全部的开发人员知道而且启用这个选项。

  • Yarn采起了不一样的作法。每一个 yarn 安装都会生成一个相似于 npm-shrinkwrap.json 的 yarn.lock 文件,并且它是默认建立的。除了常规信息以外,yarn.lock文件还包含要安装的内容的校验和,以确保使用的库的版本相同。

  • yarn 是通过从新设计的崭新的 npm 客户端,它能让开发人员并行处理全部必须的操做,并添加了一些其余改进。

  • 运行速度获得了显著的提高,整个安装时间也变得更少

  • 像 npm 同样,yarn 使用本地缓存。`与npm不一样的是,yarn无需互联网链接就能安装本地缓存的依赖项,它提供了离线模式`

  • 容许合并项目中使用到的全部的包的许可证

  • 一般状况下不建议经过 npm 进行安装。npm 安装是非肯定性的,程序包没有签名,而且 npm 除了作了基本的 SHA1 哈希以外不执行任何完整性检查,这给安装系统程序带来了安全风险。(做者曾经在一个上百个依赖包的项目中使用npm丢包过,代价很是大,泪水不自觉掉下来)

首先看一次很是失败的包下载 居然是从全局读取的资源 (不配置webpack别名是由于就这一个路径这么长)

640?wx_fmt=png

首先咱们从原理入手 ,咱们使用 npm inityarn init ,cnpm init 的时候 发生了什么 ?

  • 生成package.json文件

  • json文件内部声明初始的版本信息、做者信息等,若是你是须要上传到 npm 上做为命令行工具,应该配置bin等声明入口字段

那么当咱们使用npm i , yarn add ,cnpm i 操做时候会发生什么 ?

  • 首先会根据你的命令行后缀是否加了 -g 或者global判断,下载的包是放在全局的环境,仍是当前package.json文件对应的node_module文件夹目录下 (这点尤为重要,有人出 BUG,就是由于在用npm , cnpm时候没有注明添加的是全局依赖仍是本地依赖,致使json文件上没有对应的包名,项目永远起不来)

  • 而后根据你的指令--save 或者-D--save -dev判断是开发依赖仍是线上依赖,其实这点在yarn上没有问题,由于yarn有本身的一套检查包完整性的机制,不会丢包,还会自动判断添加依赖,出bug通常是cnpmnpm,没有明确-g或者--savenpm只有检查程序员签名的机制,没有检查包完整性的机制,也不会自动添加依赖到json文件,那么就会出现丢包的假象,因此建议主要使用`yarn`

yarn 和 npm 对比

640?wx_fmt=png

npm 的缺点汇总:

  • 同一个项目,安装的时候没法保持一致性。因为 package.json 文件中版本号的特色,下面三个版本号在安装的时候表明不一样的含义。

    "5.0.3",
    "~5.0.3",
    "^5.0.3"
  • “5.0.3” 表示安装指定的 5.0.3 版本,“~5.0.3” 表示安装 5.0.X 中最新的版本,“^5.0.3” 表示安装 5.X.X 中最新的版本。这就麻烦了,经常会出现同一个项目,有的同事是 OK 的,有的同事会因为安装的版本不一致出现bug

  • 安装的时候,包会在同一时间下载和安装,中途某个时候,一个包抛出了一个错误,可是 npm 会继续下载和安装包。由于 npm 会把全部的日志输出到终端,有关错误包的错误信息就会在一大堆npm打印的警告中丢失掉,而且你甚至永远不会注意到实际发生的错误。

`yarn`的优势

  • 速度快 。速度快主要来自如下两个方面:

  • 并行安装:不管 npm 仍是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每一个 package,也就是说必需要等到当前 package 安装完成以后,才能继续后面的安装。而 Yarn 是并行执行全部任务,提升了性能。

离线模式:若是以前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了

  • 安装版本统一:为了防止拉取到不一样的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会建立(或更新)yarn.lock 这个文件。这么作就保证了,每一次拉取同一个项目依赖时,使用的都是同样的模块版本。npm 其实也有办法实现到处使用相同版本的 packages,但须要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 二者的不一样之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要经过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。

  • 更简洁的输出:npm 的输出信息比较冗长。在执行 npm install 的时候,命令行里会不断地打印出全部被安装上的依赖。相比之下,Yarn 简洁太多:默认状况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。

  • 多注册来源处理:全部的依赖包,无论他被不一样的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。

  • 更好的语义化: yarn改变了一些npm命令的名称,好比 yarn add/remove,感受上比 npm 本来的 install/uninstall 要更清晰。

那不是标题党? 说了yarn这么多优势,咱们为何还要npm呢?

你不用npm publish ,你怎么上传包到npm? 你不用cnpm,是下载不了一些包的

搞清楚三者下载包(依赖)的本质结果:

  • 首先向对应的node_module文件夹下面下载包(若是你非要下到全局,那么再见)

  • 再而后是json文件中添加对应的依赖字段, 肯定是线上依赖仍是开发依赖

  • 只要作到这二者 你就下包成功

  • 总结就是 只要结果 过程管你是啥

使用yarn下载过的包,再使用npm cnpm下载 会重复下载,删除以前的包

  • puppeteer这个包所依赖的mini版谷歌浏览器使用cnpm下载就能够完美解决

  • prerender-spa-plugin这个包依赖上面的木偶戏 puppeteer这个包,也能够用cnpm下载

  • 混合使用包管理器切记,不要重复下载依赖,npm cnpm下载依赖,必定要添加注明是什么依赖,是否全局安

  • yarnnpm i二者,选择前者,缘由在上面有提到,整体来讲,yarn是不二选择,可是其余二者也不可缺乏,好比electron这个依赖,使用cnpm就能够完美一键安装

只要胆大心细,就能够把三者用得如鱼得水,否则就会被按在地上摩擦,实践过程踩坑也是正常 以为写得好别忘了关注个人专栏,给个赞再走~

原文做者:Peter谭金杰

地址:https://segmentfault.com/a/1190000019299845


原创系列推荐

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门手册(共 18 章)(上)

6. Webpack4 入门手册(共 18 章)(下)

7. 59篇原创系列汇总 

640?wx_fmt=png

640?wx_fmt=png

点这,与你们一块儿分享本文吧

相关文章
相关标签/搜索