官方说明:https://classic.yarnpkg.com/zh-Hans/docs/package-json
原文地址:yarn命令的使用
name
和 version
是 package.json
文件里最重要的两个字段,没有它们你的包无法被安装。 name
和 version
字段一起用来创建一个唯一 id。
yarn add [name]
这是你的包的名字。它在 URL 中、作为命令行参数、作为 node_modules
里的目录名使用。
node_modules/[name] https://registry.npmjs.org/[name]/-/[name]-[version].tgz
添加一个依赖
通过
yarn add
添加依赖会更新package.json
以及yarn.lock
文件
yarn add <packageName>
依赖会记录在package.json
的dependencies
yarn global add <packageName>
全局安装依赖
更新一个依赖
yarn upgrade
用于更新包到基于规范范围的最新版本
yarn upgrade --latest # 忽略版本规则,升级到最新版本,并且更新 package.json
移除一个依赖
yarn remove <packageName>
安装 package.json 中的所有文件
yarn
或者yarn install
运行脚本
yarn run
用来执行在package.json
中scripts
属性下定义的脚本
// package.json
{
"scripts": {
"dev": "node app.js",
"start": "node app.js"
}
}
yarn run dev # yarn 执行 dev 对应的脚本 node app.js
npm run # npm
yarn start # yarn
npm start # npm
与 npm 一样 可以有
yarn start
和yarn test
两个简写的运行脚本方式
显示某个包信息
列出项目的所有依赖
yarn list
# 列出当前项目的依赖
yarn global list # 列出全局安装的模块
原文地址:
理一理 npm, yarn, package.json, pakage-lock.json, yarn.lock 之间的关系
package-lock.json和yarn.lock的包依赖区别
npm
的全称是 Node Package Manager,简单来说它就是一个包 (package) 管理工具。npm
的公司买了一个仓库用来存放这些我们日常所用的包,我们只需要安装npm
,就能很轻易的通过npm
来很方便的安装这些包了。node包管理
包是一段可以复用的代码,这段代码可以从全局注册表下载到开发者的本地环境。每个包可能会,也可能不会依赖于别的包。简单地说,包管理器是一段代码,它可以让你管理依赖(你或者他人写的外部代码),你的项目需要这些依赖来正确运行。
npm
简化了我们安装各类包的过程,而package.json
的作用就是记录我们用npm
安装过哪些包的。package.json
可以通过初始化语句npm init
来生成,刚生成的package.json
的"dependencies"
里面是空的,随着你逐渐通过npm
安装各类包,安装过哪些包,版本号是什么,都会记录在"dependencies"
里面package.json
一起交给别人,他就能知道要运行这个目需要安装哪些包了。更方便的是,他只要在自己的电脑上输入npm install
,npm
就会自动安所有这些需要的包。为啥我们需要一个包管理工具呢?因为我们在Node.js
上开发时,会用到很多别人写的JavaScript
代码。如果我们要使用别人写的某个包,每次都根据名称搜索一下官方网站,下载代码,解压,再使用,非常繁琐。
更重要的是,如果我们要使用模块A,而模块A又依赖于模块B,模块B又依赖于模块C和模块D,npm
可以根据依赖关系,把所有依赖的包都下载下来并管理起来。否则,靠我们自己手动管理,肯定既麻烦又容易出错。
于是一个集中管理的工具应运而生:
- 大家都把自己开发的模块打包后放到
npm
官网上,如果要使用,直接通过npm
安装就可以直接用,不用管代码存在哪,应该从哪下载。 Yarn
是为了弥补npm
的一些缺陷[速度慢,稳定性高]而出现的。”
npm
npm
为你和你的团队打开了连接整个JavaScript
天才世界的一扇大门。它是世界上最大的软件注册表,每星期大约有 30 亿次的下载量,包含超过 600000 个 包(package
) (即,代码模块)。来自各大洲的开源软件开发者使用npm
互相分享和借鉴。包的结构使您能够轻松跟踪依赖项和版本。
下面是关于 npm
的快速介绍:npm
由三个独立的部分组成:
- 网站
网站 是开发者查找包(package
)、设置参数以及管理npm
使用体验的主要途径。 - 注册表(
registry
)
注册表 是一个巨大的数据库,保存了每个包(package
)的信息。 - 命令行工具 (
CLI
)CLI
通过命令行或终端运行。开发者通过 CLI 与 npm 打交道。
yarn
Yarn
发布于2016年10月,并在Github
上迅速拥有了2.4万个Star。而npm
只有1.2万个star
。这个项目由一些高级开发人员维护,包括了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 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。
- 离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。
- 安装版本统一:为了防止拉取到不同的版本,
Yarn
有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock
这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。 - 更好的语义化:
yarn
改变了一些npm
命令的名称,比如yarn add/remove
,感觉上比 npm 原本的install/uninstall
要更清晰。
node包的安装
-
执行工程自身
preinstall
- 当前 npm 工程如果定义了
preinstall
钩子此时会被执行。
- 当前 npm 工程如果定义了
-
确定首层依赖
- 模块首先需要做的是确定工程中的首层依赖,也就是
dependencies
和devDependencies
属性中直接指定的模块(假设此时没有添加npm install
参数)。工程本身是整棵依赖树的根节点,每个首层依赖模块都是根节点下面的一棵子树,npm 会开启多进程从每个首层依赖模块开始逐步寻找更深层级的节点。
- 模块首先需要做的是确定工程中的首层依赖,也就是
-
获取模块
- 获取模块是一个递归的过程,分为以下几步:
- 获取模块信息。在下载一个模块之前,首先要确定其版本,这是因为
package.json
中往往是semantic version
(semver,语义化版本)。此时如果版本描述文件(npm-shrinkwrap.json
或package-lock.json
)中有该模块信息直接拿即可,如果没有则从仓库获取。如packaeg.json
中某个包的版本是^1.1.0,npm
就会去仓库中获取符合1.x.x
形式的最新版本。 - 获取模块实体。上一步会获取到模块的压缩包地址(
resolved
字段),npm 会用此地址检查本地缓存,缓存中有就直接拿,如果没有则从仓库下载。 - 查找该模块依赖,如果有依赖则回到第1步,如果没有则停止。
-
模块扁平化(
dedupe
)- 上一步获取到的是一棵完整的依赖树,其中可能包含大量重复模块。比如 A 模块依赖于
loadsh
,B 模块同样依赖于lodash
。在 npm3 以前会严格按照依赖树的结构进行安装,因此会造成模块冗余。yarn
和从npm5
开始默认加入了一个dedupe
的过程。它会遍历所有节点,逐个将模块放在根节点下面,也就是node-modules
的第一层。当发现有重复模块时,则将其丢弃。这里需要对重复模块进行一个定义,它指的是模块名相同且semver
兼容。每个semver
都对应一段版本允许范围,如果两个模块的版本允许范围存在交集,那么就可以得到一个兼容版本,而不必版本号完全一致,这可以使更多冗余模块在dedupe
过程中被去掉。
- 上一步获取到的是一棵完整的依赖树,其中可能包含大量重复模块。比如 A 模块依赖于
-
安装模块
- 这一步将会更新工程中的
node_modules
,并执行模块中的生命周期函数(按照preinstall、install、postinstall
的顺序)。
- 这一步将会更新工程中的
-
执行工程自身生命周期
- 当前 npm 工程如果定义了钩子此时会被执行(按照
install、postinstall、prepublish、prepare
的顺序)。
- 当前 npm 工程如果定义了钩子此时会被执行(按照
Pakage-lock.json文件的作用
在5.X.X
之后的npm
版本中,pakage-lock.json
是会被自动生成的。pakage-lock.json
被创建的目的就是更精确的记录包的各类信息。
version
记录了包的版本,resolved
记录了包的下载来源。这样,在通过npm install
命令安装时,不仅能够安装相同版本号的包,而且连包的下载源都是一样的,这样,我们就实现了真正意义上的安装一模一样的依赖包,从而确保程序的成功运行。
那么我们在有了pakage-lock.json
后是不是就不需要package.json
了呢?不,我们依旧需要package.json
。这两个文件之间的关系可以这样来理解:package.json
负责的不仅仅是记录各种依赖包,它还记录了其他信息,包括project properties
, description
, author
& license
等等,而pakage-lock.json
的作用仅仅是辅助package.json
锁定依赖包的版本。pakage-lock.json
可有可无,没有的话只是不能锁定版本而已,而package.json
是必须要有的。
lock文件
锁文件是由包管理器自动生成的。它包含了重现全部的依赖源码树需要的所有信息、你的项目依赖中的所有信息,以及它们各自的版本。
现在值得强调的是,Yarn
使用了锁文件,而 npm5
以前没有默认锁文件,npm5
之后加入了默认锁文件功能。我们会谈到这种差别导致的一些后果。既然我已经向你介绍了包管理器这部分,现在我们来讨论依赖本身。
目前常见的两种lock文件:
packahe-lock.json
是npm5之后默认生成的锁文件yarn.lock
是yarn的锁文件
yarn.lock解析
显然yarn.lock锁文件把所有的依赖包都扁平化的展示了出来,对于同名包但是semver不兼容的作为不同的字段放在了yarn.lock的同一级结构中。
yarn.lock文件
yarn.lock 锁定了安装包的精确版本以及所有依赖项。有了这个文件,你可以确定项目团队的每个成员都安装了精确的软件包版本,部署可以轻松地重现,且没有意外的 bug,并且这个文件可以使得程序在不同的机器上可以攻取一致的体验
Yarn 锁定文件的和安装算法的存在,确保了将应用程序部署到生产环境时,安装的依赖在开发机器之间,产生的文件和文件夹结构完全相同。