多项目多包
多个包对应多个独立项目,好处是符合单一职责原则,简单可靠,但是这种方案在某些情况下会有一些问题
问题:ssp 中的代码同步问题
ssp 项目前端部分区分了两个项目,但两个项目实际上基于一致的框架实现业务逻辑,因此有很多通用的业务逻辑,组件需要在两个项目中共享,
初期是 ctrl + c/v
后来项目组内搭建了私有 npm 仓库,所以考虑用 npm package 同步代码,假如按照多包多项目的管理方式 Ï · 代码/组件相对细小,如果单独拆分项目则过于零散。
· 独立项目会有重复的依赖/构建流等配置,如 webpack 配置代码
· 同步代码组件的开发环境严重依赖主项目本身,独立项目不利于开发维护。
· 多个子包需要一个统一的管理方式
于是需要考虑另一种管理方式
单项目多包
顾名思义,单项目多包,就是虽然划分多个子包,但是都放到同一个项目进行管理。
这样,就解决了多个独立子项目配置重复,不便于开发维护的问题。
但是还有一个的统一管理的问题又该如何解决呢?
Lerna 解决单项目多包的管理问题
所谓的统一管理问题,举个简单的例子如果所有包都需要发布一个新版本,那么是逐个 npm publish
好还是统一执行 xxx publish
合理?
本质上这就是 lerna 在干的事
lerna 命令初见
lerna 项目中最常用到的命令是 lerna init, lerna bootstrap 和 lerna publish
lerna init
初始化项目
go
multi-packages/
package.json
packages/
package-1/
package.json
package-2/
package.json
命令执行以后,主要就是生成了以上的一个结构,其中 packages 就是默认存放多个子包的目录
lerna create
创建子包
相当于执行 npm init
,不过在执行的时候自动将创建的 package.json
放到 package/
目录下, 比如执行 lerna pacekage-3
go
multi-packages/
package.json
packages/
package-1/
package.json
package-2/
package.json
package-3/
package.json
lerna publish
发布版本,这是 lerna 最核心的命令了,运行这个命令以后会出发以下的一些东西
-
运行lerna updated来决定哪一个包需要被publish
-
如果有必要,将会更新lerna.json中的version
-
将所有更新过的的包中的package.json的version字段更新
-
将所有更新过的包中的依赖更新
-
为新版本创建一个git commit或tag
-
将包publish到npm上
lerna publish 有两种管理模式
· 一种是 fixed 模式 -- 统一版本号 @babel
· 一种是 independent 模式 -- 独立管理各个包的版本号
可以通过 lerna.json 进行配置
同时,该命令也有许多的参数,例如 --skip-git 将不会创建git commit或tag,--skip-npm将不会把包publish到npm上。
除此之外其他大都是 命令都是统一对 package/ 下的包执行某些操作不再一一赘述
有需要可以参考官方文档
npm @scope
npm 在 5.0.0 之后就全面支持了 @scope 包作用域的功能,这个功能最大的初衷就是更好的管理包的命名问题
比如以下这些包 babel- 开头的包
· babel-runtime-core
· babel-core
· babel-php-transfer
由于 npm 采取先到先得的原则,基本上没有什么办法很好的区分第三方和 babel 官方的包
而启用 @babel 命名空间之后,只要看到 @babel 就知道一定是 babel 官方的包
npm registry
不过对于我们私有包的作用上来说,规范命名还是其次,最重要的是 npm 设置 registry 的时候不仅可以全局设置,也可以针对单个 @scope 定义。
perl
// 在 @myco 命名空间下登陆状态总是指向 http://reg.example.com
npm login --registry=http://reg.example.com --scope=@myco
// 同样的,通过单独设置 @myco 命名空间的 registry ,那么就只有这个命名空间下的包,无论是 npm install/publish 都会指向你所设置的地址
npm config set @myco:registry http://reg.example.com
如果我们的给所有私有包都定义一个scope,这样的话当我们就可以根据 scope 分配私有仓库的 registry 。
从而有效区分公共/私有仓库,做到私有包访问私有仓库,公共包访问公共包仓库,不需要全部流量都走私有仓库再转发出去。
npm link
基于 npm 管理包还会遇到一个问题,当 package-A 依赖 package-B, 而 package-B 包由于某些原因需要频繁编辑,同时需要立刻在 package-A 环境下查看效果。,由于npm 包每次更新都需要修改版本号(或者 npm unpublish && npm publish
强制覆盖),如果按照正常流程则需要
css
vim package-B/package.json // 除了关键代码文件修改,还需要修改 package.json 的 version 字段
npm publish // 推送 package-B 到仓库
cd package-A/ && npm i package-B // 在 package-A 更新 package-B ,然后才能查看效果
如果是 package-B 处于一种频繁修改的状态,以上流程就会让开发调试 package-B 的过程变得非常繁琐。
而 npm link
相当于一个软链,可以将你想要安装的包软链到本地项目中。比如:
perl
cd package-B && npm link // 在 package-B 下执行,为 package-B 建立一个软链
这个时候如果再别的项目中安装 package-B,那么并不会实际安装 package-B,而是通过软链指向 package-B/
文件夹
perl
cd package-A && npm link package-B // node_modules/package-B 自动软链到 package-B/
这样,你对 package-B 的修改就可以及时反馈在 package-A 项目中了
总结
· 介绍多包多仓库,多包单仓库之间的区别,以及多包多仓库这种管理方法的一些问题
· 介绍 lerna 如何管多包单仓库项目
· 介绍基于 npm 两个有用的特性 npm @scope / npm link
Extra
cz-cli -- The commitizen command line utility.
这个工具提供一个 cli 界面帮助你规范 commit
npm install -g commitizen
使用方法
arduino
git cz // 用 cz 替换 commit 命令