Open ghost opened 7 years ago
首先说一下我为什么使用yarn代替npm。
最近在做赢财富的开发,我遇到了一个很麻烦的问题,这个问题也排除了很久才搞定。
我将赢财富源码从svn迁移到git时,顺便也把项目依赖进行了升级,比如升级到webpack 2,babel 6,react 15.x等。在我本地调试通过后,我把package.json及相关配置项推送到了服务端,按理说另外一个同事检出项目后,执行npm install命令进行依赖安装,最后会得到跟我一样的环境并且项目应该良好运行。然而,事情并不是这样。
比如,我其中两个依赖如下:
"webpack": "^2.1.0-beta.19", "webpack-dev-server": "^2.1.0-beta.0"
同事检出项目package.json文件,安装依赖之后,webpack变成了2.2.0版本,webpack-dev-server变成了2.1.0-beta.25版本,从而导致项目不能运行。
造成这种情况的原因与npm有关,npm install采用的是模糊安装,也就是它会自动寻找与package.json中指定的版本相近的稳定版本,npm的这种看似聪明的做法,实际上破坏了各个依赖之间的对等关系,从而导致虽然都是同一份配置文件,但是不同的人可能得到的安装结果不一样。
yarn发布最初的目的就是解决npm的缺陷问题。yarn与npm类似,是一款js包管理cli工具,甚至它的许多用法与npm极为相似,但是yarn更加高效、安全和可靠。
高效:yarn安装依赖项更加快速,具体的数据对比请自己体验。在我实际的使用中,比npm明显快几乎一半的时间。并且它使用了缓存机制,避免重复下载。
安全:下载之前会检查签名及包的完整性。
可靠:它利用一个yarn.lock文件来保证各个平台下得到的依赖具有一直性。
仅仅以上三点,就让我有理由使用yarn。下面我先说,如何从npm迁移到yarn,这也算是yarn和npm的对比。
安装yarn非常简单,下载yarn,然后一直下一步就行。
从npm迁移到yarn并不需要做太多的工作。
yarn与npm一样都是通过package.json文件来描述项目依赖,所以如果项目中有了npm的package.json文件,你只需要执行一个命令即可。
yarn //或者yarn install
这个命令会自动分析package.json文件,并且根据它自己的算法,重组node_modules文件夹,生成一个yarn.lock文件,然后项目之间的依赖关系就被yarn管理起来了。
然后,我们应该将package.json 和 yarn.lock文件都推送到服务端,以保证其他同事得到相同的依赖关系。
因此,更加平凡的情况是,从服务端检出项目,项目中应该包含package.json文件和yarn.lock文件。然后执行命令:
yarn命令会自动检查package.json和yarn.lock文件,并且安装这两个文件规定的依赖,依赖文件依旧安装在node_modules文件夹中。
安装完依赖之后,项目结构跟之前使用npm并没有什么不同。只不过你在安装的过程中可能已经发现了,yarn更加友好,下载速度更加快,依赖关系更加准确。
依赖安装完成之后,可以使用同npm start等一样的命令来启动项目:
yarn start //或者yarn run start ,yarn run [script]
更加详细的从npm迁移到yarn的介绍请查看这里。
实际上,yarn并不强制每一个人都必须使用yarn。上面已经提到过,yarn和npm都使用package.json来描述依赖关系,因此,yarn和npm可以共存。也就是说,其他同事仍然可以保留他的npm,并按照npm的使用方式来运行。
但是,我强烈建议大家应该都使用yarn,因为它能解决依赖不对等带来的麻烦。而它的好处正如官方所言:
what are u waiting for?
yarn与npm的使用方式相似,而且只需要记住几个命令即可。
yarn init 与 npm init一样,都是用来初始化一个项目,生成package.json文件。
可以看到这个命令跟npm init几乎一样。
直接执行yarn,其默认会执行yarn install命令。因此,这两种写法的执行结果是一样的。
yarn [install] //同 npm install一样
yarn install与直接执行npm install的效果是一样的,都是安装所有的package.json文件指定的依赖文件。
不同的是yarn install会生成一个yarn.lock文件,或者根据yarn.loack文件(yarn.loack文件已经存在)加载更加确定可靠的依赖。并且package.json和yarn.lock会保持同步更新,新加到package.json中的依赖也会同步更新到yarn.lock。
关于yarn.lock文件后面再解释,在这里就把它当做一个锁文件,这个锁保证加载到的依赖都是确定可靠的。
yarn add用来添加一个新依赖。于npm不同的是,npm添加一个新依赖依旧使用npm install xxx.name命令。
安装新依赖时,同npm一样可以指定版本号,选择安装到全局环境或者本地环境,作为项目运行依赖或者开发依赖。
yarn add [package] //和npm install --save [package]一样
yarn add [package]会添加并安装指定的依赖,并且默认加到package.json文件中,同npm install --save [package]的效果一样。
yarn add [package]
npm install --save [package]
在安装依赖时,仍然可以指定版本号:
yarn add [package@version]
甚至可以使用git上的tag作为版本号:
yarn add [package@tag]//这个tag是指推送到了git,但是还没有发布的版本
yarn的全局安装需要添加global前缀:
yarn global add [package]//和npm install --global [package]一样
与npm的全局安装不同的是,npm的全局安装是使用-g或者--global参数,而yarn是则是在命令前加前缀,而且globa只能加载add前面。
还可以将依赖项安装为开发依赖,从而避免打包工具打包到生产环境,比如mocha、babel等工具就应该被安装为开发依赖。
yarn add [package] [--dev/-D] //和npm install --save-dev [package]一样
yarn新增了一个对等依赖选项,它可以新增一个包并将包声明为对等依赖,表明该项目需要这个对应的依赖包才能正常运行。
yarn add [package] [--peer/-P]
这个命令会在package.json文件中,生成一个peerDependencies属性。比如:
"peerDependencies": { "babel": "^6.5.2" }
这样就表明了该项目需要对等的babel@^6.5.2才能运行,这与npm的peerDependencies一样,只不过yarn使用明确的参数来声明。
对等依赖在执行yarn时并不会自动安装。也就是另外的同事在检出package.json文件时,如果包含对等依赖,那么这些依赖不会自动安装,yarn只会提示你需要安装这些依赖,所以你需要手动安装这些依赖。
移除一个依赖使用如下命令:
yarn remove [package]
与npm不同的是,npm使用npm uninstall命令,并且npm uninstall可以具有--save、--save-dev等参数。而yarn移除依赖,均只使用yarn remove,package.json文件也会自动被更新。
npm uninstall
使用yarn run运行package script命令。同npm run 命令一样。
yarn run [script] //npm run [script]
这里yarn start 依然是yarn run start的简写形式。
yarn start
yarn run start
yarn upgrade
这个命令会升级package.json中的所有依赖包,但是,它只会升级到package.json指定的版本区间的最新版本。并且lock文件也会被同步更新。
这种情况通常出现在别人升级了项目依赖,你获取package.json文件后,使用这个命令来更新依赖,以便跟他同步,跟npm update类似。
npm update
yarn upgrade [package]
指定包名的情况就比较有意思了,这会更新你指定的某个包。但是,它会更新到包仓库中现在最新的稳定版本,也就是指定包名,它不一定会升级依赖的版本,还可能会降低版本。
比如,我刚才安装了两个依赖:
"dependencies": { "webpack": "2.1.0-beta.19", "webpack-dev-server": "2.1.0-beta.0" }
然后指定包名,升级webpack:
yarn upgrade webpack
查看package.json文件:
"dependencies": { "webpack": "^1.14.0", "webpack-dev-server": "2.1.0-beta.0" }
webpack的版本没有增加,反而降低了。这是因为,它默认使用了包仓库中的稳定版本。我们一样可以指定版本,来更新到特定的版本:
yarn upgrade [package@version/tag]
这个命令通常用来清空缓存:
yarn cache clean //npm cache clean
yarn publish
用于将代码发布到npm仓库,具体的发布过程这里不再阐述。
掌握以上命令和使用方法,已经足够我们日常开发了。如果需要了解它的更多用法,请移步官网。
前面一直提到,yarn可以保证依赖的可靠性,这种可靠性就是通过yarn.lock文件来完成的。
yarn推出之处,正如官方所言,它是为了弥补npm的缺陷而出现的:
yarn既然只是为了弥补npm的缺陷,那么它就并不会完全取代npm,它只是在npm的基础上进行了完善和优化,因此,yarn拉取的package依旧来自npm仓库。
既然拉取的包依然来自npm仓库,仓库本身不会变,所以获取的的模板包的版本就应该一样,那么它是如何保证在不同机器环境下获得一致的版本的呢?
这就有了yarn.lock这个文件。
我们已经知道了yarn和npm一样都是使用package.json来描述项目依赖,但是package.json中的版本号往往不会写的太确切,通常是一个版本区间。这个版本区间规定了大版本号和小版本号,从npm仓库拉取依赖时,会根据这个版本区间来选择一个最新的已经修复了BUG的稳定版本。
这种看似聪明的做法,实际上会为项目带来BUG,甚至完全不能运行。为了防止拉取到不同的版本,yarn使用了lock文件来进一步描述这种依赖关系,yarn.lock文件可以看做是package.json文件的补充。
每新增或更新一个依赖时,yarn就会创建(更新)lock文件,并把这次安装的确定版本号记录在lock文件中。当我们把package.json文件和yarn.lock文件交给其他人时,他通过执行yarn命令,就会得到跟你一模一样的模块版本。
yarn比npm更好用:具有锁文件,保证依赖一直性;并行下载,更快的安装速度;离线下载模式进一步提升速度;自检查保证包完整性;并且从npm转到yarn几乎是零成本。
使用yarn代替npm
首先说一下我为什么使用yarn代替npm。
最近在做赢财富的开发,我遇到了一个很麻烦的问题,这个问题也排除了很久才搞定。
我将赢财富源码从svn迁移到git时,顺便也把项目依赖进行了升级,比如升级到webpack 2,babel 6,react 15.x等。在我本地调试通过后,我把package.json及相关配置项推送到了服务端,按理说另外一个同事检出项目后,执行npm install命令进行依赖安装,最后会得到跟我一样的环境并且项目应该良好运行。然而,事情并不是这样。
比如,我其中两个依赖如下:
同事检出项目package.json文件,安装依赖之后,webpack变成了2.2.0版本,webpack-dev-server变成了2.1.0-beta.25版本,从而导致项目不能运行。
造成这种情况的原因与npm有关,npm install采用的是模糊安装,也就是它会自动寻找与package.json中指定的版本相近的稳定版本,npm的这种看似聪明的做法,实际上破坏了各个依赖之间的对等关系,从而导致虽然都是同一份配置文件,但是不同的人可能得到的安装结果不一样。
yarn发布最初的目的就是解决npm的缺陷问题。yarn与npm类似,是一款js包管理cli工具,甚至它的许多用法与npm极为相似,但是yarn更加高效、安全和可靠。
高效:yarn安装依赖项更加快速,具体的数据对比请自己体验。在我实际的使用中,比npm明显快几乎一半的时间。并且它使用了缓存机制,避免重复下载。
安全:下载之前会检查签名及包的完整性。
可靠:它利用一个yarn.lock文件来保证各个平台下得到的依赖具有一直性。
仅仅以上三点,就让我有理由使用yarn。下面我先说,如何从npm迁移到yarn,这也算是yarn和npm的对比。
安装yarn
安装yarn非常简单,下载yarn,然后一直下一步就行。
在现在的项目中使用yarn
从npm迁移到yarn并不需要做太多的工作。
yarn与npm一样都是通过package.json文件来描述项目依赖,所以如果项目中有了npm的package.json文件,你只需要执行一个命令即可。
这个命令会自动分析package.json文件,并且根据它自己的算法,重组node_modules文件夹,生成一个yarn.lock文件,然后项目之间的依赖关系就被yarn管理起来了。
然后,我们应该将package.json 和 yarn.lock文件都推送到服务端,以保证其他同事得到相同的依赖关系。
因此,更加平凡的情况是,从服务端检出项目,项目中应该包含package.json文件和yarn.lock文件。然后执行命令:
yarn命令会自动检查package.json和yarn.lock文件,并且安装这两个文件规定的依赖,依赖文件依旧安装在node_modules文件夹中。
安装完依赖之后,项目结构跟之前使用npm并没有什么不同。只不过你在安装的过程中可能已经发现了,yarn更加友好,下载速度更加快,依赖关系更加准确。
依赖安装完成之后,可以使用同npm start等一样的命令来启动项目:
更加详细的从npm迁移到yarn的介绍请查看这里。
yarn与npm共存
实际上,yarn并不强制每一个人都必须使用yarn。上面已经提到过,yarn和npm都使用package.json来描述依赖关系,因此,yarn和npm可以共存。也就是说,其他同事仍然可以保留他的npm,并按照npm的使用方式来运行。
但是,我强烈建议大家应该都使用yarn,因为它能解决依赖不对等带来的麻烦。而它的好处正如官方所言:
what are u waiting for?
yarn的使用方法
yarn与npm的使用方式相似,而且只需要记住几个命令即可。
yarn init
yarn init 与 npm init一样,都是用来初始化一个项目,生成package.json文件。
可以看到这个命令跟npm init几乎一样。
yarn / yarn install
直接执行yarn,其默认会执行yarn install命令。因此,这两种写法的执行结果是一样的。
yarn install与直接执行npm install的效果是一样的,都是安装所有的package.json文件指定的依赖文件。
不同的是yarn install会生成一个yarn.lock文件,或者根据yarn.loack文件(yarn.loack文件已经存在)加载更加确定可靠的依赖。并且package.json和yarn.lock会保持同步更新,新加到package.json中的依赖也会同步更新到yarn.lock。
关于yarn.lock文件后面再解释,在这里就把它当做一个锁文件,这个锁保证加载到的依赖都是确定可靠的。
yarn add
yarn add用来添加一个新依赖。于npm不同的是,npm添加一个新依赖依旧使用npm install xxx.name命令。
安装新依赖时,同npm一样可以指定版本号,选择安装到全局环境或者本地环境,作为项目运行依赖或者开发依赖。
yarn add [package]
会添加并安装指定的依赖,并且默认加到package.json文件中,同npm install --save [package]
的效果一样。在安装依赖时,仍然可以指定版本号:
甚至可以使用git上的tag作为版本号:
yarn的全局安装需要添加global前缀:
与npm的全局安装不同的是,npm的全局安装是使用-g或者--global参数,而yarn是则是在命令前加前缀,而且globa只能加载add前面。
还可以将依赖项安装为开发依赖,从而避免打包工具打包到生产环境,比如mocha、babel等工具就应该被安装为开发依赖。
yarn新增了一个对等依赖选项,它可以新增一个包并将包声明为对等依赖,表明该项目需要这个对应的依赖包才能正常运行。
这个命令会在package.json文件中,生成一个peerDependencies属性。比如:
这样就表明了该项目需要对等的babel@^6.5.2才能运行,这与npm的peerDependencies一样,只不过yarn使用明确的参数来声明。
对等依赖在执行yarn时并不会自动安装。也就是另外的同事在检出package.json文件时,如果包含对等依赖,那么这些依赖不会自动安装,yarn只会提示你需要安装这些依赖,所以你需要手动安装这些依赖。
yarn remove
移除一个依赖使用如下命令:
与npm不同的是,npm使用
npm uninstall
命令,并且npm uninstall可以具有--save、--save-dev等参数。而yarn移除依赖,均只使用yarn remove,package.json文件也会自动被更新。yarn run
使用yarn run运行package script命令。同npm run 命令一样。
这里
yarn start
依然是yarn run start
的简写形式。yarn upgrade
这个命令会升级package.json中的所有依赖包,但是,它只会升级到package.json指定的版本区间的最新版本。并且lock文件也会被同步更新。
这种情况通常出现在别人升级了项目依赖,你获取package.json文件后,使用这个命令来更新依赖,以便跟他同步,跟
npm update
类似。指定包名的情况就比较有意思了,这会更新你指定的某个包。但是,它会更新到包仓库中现在最新的稳定版本,也就是指定包名,它不一定会升级依赖的版本,还可能会降低版本。
比如,我刚才安装了两个依赖:
然后指定包名,升级webpack:
查看package.json文件:
webpack的版本没有增加,反而降低了。这是因为,它默认使用了包仓库中的稳定版本。我们一样可以指定版本,来更新到特定的版本:
yarn cache
这个命令通常用来清空缓存:
yarn publish
用于将代码发布到npm仓库,具体的发布过程这里不再阐述。
掌握以上命令和使用方法,已经足够我们日常开发了。如果需要了解它的更多用法,请移步官网。
yarn.lock文件
前面一直提到,yarn可以保证依赖的可靠性,这种可靠性就是通过yarn.lock文件来完成的。
yarn推出之处,正如官方所言,它是为了弥补npm的缺陷而出现的:
yarn既然只是为了弥补npm的缺陷,那么它就并不会完全取代npm,它只是在npm的基础上进行了完善和优化,因此,yarn拉取的package依旧来自npm仓库。
既然拉取的包依然来自npm仓库,仓库本身不会变,所以获取的的模板包的版本就应该一样,那么它是如何保证在不同机器环境下获得一致的版本的呢?
这就有了yarn.lock这个文件。
我们已经知道了yarn和npm一样都是使用package.json来描述项目依赖,但是package.json中的版本号往往不会写的太确切,通常是一个版本区间。这个版本区间规定了大版本号和小版本号,从npm仓库拉取依赖时,会根据这个版本区间来选择一个最新的已经修复了BUG的稳定版本。
这种看似聪明的做法,实际上会为项目带来BUG,甚至完全不能运行。为了防止拉取到不同的版本,yarn使用了lock文件来进一步描述这种依赖关系,yarn.lock文件可以看做是package.json文件的补充。
每新增或更新一个依赖时,yarn就会创建(更新)lock文件,并把这次安装的确定版本号记录在lock文件中。当我们把package.json文件和yarn.lock文件交给其他人时,他通过执行yarn命令,就会得到跟你一模一样的模块版本。
总结
yarn比npm更好用:具有锁文件,保证依赖一直性;并行下载,更快的安装速度;离线下载模式进一步提升速度;自检查保证包完整性;并且从npm转到yarn几乎是零成本。