【前端架构】大型前端项目的组织设计 - monorepo, lerna
首先介绍multirepo, monorepo概念。
multirepo
multirepo, 顾名思义,就是将应用按照模板分别在不同的仓库中进行管理。
monorepo
而monorepo就是将应用中的所有模块一股脑儿全部放在同一个项目中,不需要单独发包,测试,且所有代码都在一个项目中管理,一同部署上线,能够再开发阶段最早的发现bug, 发现问题。
Babel和React都是典型的monorepo, 其issues和Full Request都集中在唯一的项目中,changelog可以简单第从一份commits列表中梳理出来。
使用lerna实现monorepo
初始化
mkdir new-monorepo
cd new-monorepo
npm init -y
npm - -g monorepo
lerna init
以上初始化成功以后,会出现以下文件
packages
lerna.json
packages.json
新建子模块
mkdir module-1
cd module-1
npm init -y
mkdir module-2
cd module-2
npm init -y
mkdir module-3
cd module-3
npm init -y
然后,退回主目录,安装依赖。
cd
lerna bootstrap
lerna bootstrap命令会简历整个项目内子应用和模块之前的依赖关系,这种建立关系不是通过硬安装,而是通过软链指向相关依赖的。
如果需要发布到npm中, 可以通过lerna publish来实现。
lerna publish
至此,你可能觉得lerna还挺简单,但其实里面还有更多学问。如Lerna支持以下两种模块。
Fixed/Locked模块
Independent模块
我们可以通过Lerna安装依赖,该命令可以再想买下的任何文件中执行。
Lerna add dependancyName
比如:Lerna add jquery
这种方式会在父文件夹的node_modules中高效安装dependencyName依赖(Node.js 会向上在祖先文件中查找依赖)。对于未开启hoist的情况。执行lerna add后执行以下命令。
lerna bootstrap --hoist
如果我们想选择的升级某个依赖,比如只想为module-1升级dependencyName依赖的版本,就可以使用scope参数。
lerna add dependencyName --scope-module-1
项目迁移至monorepo
步骤1: 使用lerna构建monorepo项目
mkdir my-new-monorepo && cd my-new-monorepo
git init
lerna init
步骤2:导入已有项目
lerna import ./demo --flatten
步骤3:依赖维护与发布
lerna bootstrap
在这里,并不是每次都需要执行lerna bootstrap, 在第一次切换到项目,安装所有依赖时执行一次即可。
受益于monorepo, 所有项目得以集中管理在一个仓库中,这样我们便可以将所有package中公共的npm脚本移到./scripts文件中,且可以再单一monorepo项目的不同包之间构建脚本了。
依赖关系简介
说到项目中的依赖关系,我们往往会想到使用yarn/npm解决依赖关系。依赖关系大体上可以分为嵌套依赖和扁平依赖。
对于嵌套依赖和扁平依赖,npm给出了不同的处理方案。npm3以下的版本在安装依赖时非常直接,它会按照包依赖的树形结构将其下载到本地node_modules目录中,也就是说,每个包会将该包的依赖放到当前包所在的node_modules中。
npm3 采用了扁平结构,在安装依赖包时更加智能,具体体现在:在安装依赖包时, npm3会按照package.json中声明的顺序依次安装包,遇到新的包就把它放在第一级node_modules目录中。后面再进行安装时,如果遇到一级node_modules目录已经存在的包,就会先判断包版本,如果版本一样则跳过安装,否则会按照npm2的方式安装在树形目录结构下。
npm3这种安装方式只能够解决依赖重复的问题,对于一些复杂场景,依然无法做到将依赖去重,这时候就用了 npm dedupe命令。
使用yarn workspace管理依赖关系
monorepo项目找那个的依赖管理问题知得重视。现在来看一下非常流行的yarn workspace是如何处理这种问题的。
待续。