包管理工具
Posted by 付辉 on Friday, March 30, 2018 共1982字反思之前的过程,一直没有试图跟上技术的发展。恍然觉得,其实技术比买股票更能让我找到快乐。新的技术越来越多,能做的便是,持续保持蜗牛锲而不舍的精神,慢慢爬!
首先感谢这篇文章2018 年了,你还是只会 npm install 吗?,让我重新开始审视包管理工具。因为在PHP
开发中有Composer,在Go
的开发中有glide。但却没有尝试思考它们背后的那些为什么。
npm包管理
我一直不理解package.json
和package-lock.json
这两个文件的作用。直观上看,前者是我们项目所依赖的包,后者是各个包自身的明细依赖。但这样的设计却是经过多个版本迭代最终确定的形式。
当我们执行install
或者update
的时候,package-lock.json
会根据nodemodules
的更新而进行相应更新。当前就理解到这里,请看Composer
包的版本
包的版本号采用semver
约束,由3个数字组成,格式必须为 MAJOR.MINOR.PATCH
, 意为: 主版本号.小版本号.修订版本号。
约束还有一条:主版本号相同的升级版本必须提供向下兼容,但这仅仅是口头约束。测试版本的匹配,可以访问网址:https://semver.npmjs.com/。
- ^开头的版本:主版本号相同,大于等于小版本号的所有版本。
- ~开头的版本:主版本、小版本号相同,大于等于修正版本的版本。
- *或者x的版本:两者表示通配符。
- 在常规仅包含数字的版本号之外:表示不稳定的发布版本。
管理依赖
有时候,项目和项目之间存在引用依赖关系。比如将多个项目间共同使用的类在common
项目下维护,然后其他项目project-1
和project-2
分别引用项目common
。当project
项目变得越来越多时,每次新的项目都需要手动拷贝common
代码。
可以将common
做为一个包来管理。创建package.json
文件,将common
项目托管到git仓库。执行npm install git_url
就可以将common作为依赖包进行安装了。
npm除了安装git仓库的代码,也可以安装本地的代码。
npm install file:local-package-path
版本管理
svn
或者git
只需要提交package.json
, package-lock.json
, 不需要提交node_modules
目录。
每次升级或降级版本,执行如下代码,相应的package.json
,package-lock.json
会自动更新:
npm install <package-name>@<version>
删除依赖包:
npm uninstall <package>
Composer管理
Composer
生成的包管理目录叫vendor
,它也是生成两个文件composer.lock
和composer.json
。composer.lock
描述了项目的依赖以及其它的一些元信息。
composer.lock
用来明确锁定安装包的具体版本信息,包证所有人安装的版本都是一致的。具体的原因在于:
composer.json
中指定的安装包版本,比如^2.0
,只能确定该包的主版本号一定是2
,当Composer
在install
的过程中,具体安装了该包符合条件的哪个版本,是无法从.json
中看出来的。- 同理,还是上面的例子,如果一个同事,数月前执行
install
安装的版本是2.0.0
,后来这个包在2
版本下发布了一个小版本2.1.0
。另一个同事后来执行install
,很可能就安装成了2.1.0
综上所述,composer.lock
用来保证安装包的一致性,避免安装到不同的版本包,给生产环境带来的不确定性。
install/update
install
主要用来安装新包。当安装新包的时候,需要首先查看.lock
文件是否存在,如果存在,安装.lock
中指定的具体版本。如果不存在,直接安装。同时更新.json
和.lock
两个文件。
update
主要用来更新.lock
中安装的包。随着时间的推移,.json
中的包可能又发布了新版本,所以update
就是用来检查.json
中包的新版本,更新.lock
文件用的。
我在使用的过程中,比较倾向于使用下面的单个包操作的方式:
php composer.phar update monolog/monolog [...]
版本管理
在git
环境中.json
和.lock
都需要被提交的版本控制。vendor
目录就不需要啦。
Go
下的版本管理工具
glide
glide是go
的版本管理工具。其实glide
也是参考composer
设计的,所以上面对composer
的说法也同样有效。
在项目开发中也仅需要对 glide.yaml
和 glide.lock
进行版本控制,vendor目录可以忽略掉。
注:vendor
目录默认会在项目下生成。需要特别注意的是:go
的项目必须在gopath
路径下的src
目录下。
govendor
另一个版本管理工具是govendor
。它做的只是对包的管理工作,如果编译过程中缺少了引用的包,我们需要先执行go get
下载该包,然后通过govendor add +external
将包拷贝到vendor
目录。
比较实用的指令:
# 外部包,即被 $GOPATH 管理,但不在 vendor 目录下
govendor add +e
# 从线上远端库添加或更新标签或分支等于v1的依赖包
govendor fetch golang.org/x/net/context@=v1
# 本地存在vendor.json 时候拉取依赖包,匹配所记录的版本
govendor sync -v