包管理工具
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