基于 Lerna 的 monorepo 实现跨项目组件共享
source link: https://jelly.jd.com/article/6419a07bdecc790068411058
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
最近有个项目,有着多个代码库,其中有插件、业务组件等相互依赖,在开发过程中,面临着来回切项目、包版本控制、不好调试等问题,这里来探索一种新的开发管理方式来解决上述痛点,即基于lerna的monorepo实现方式
二、Lerna
A tool for managing JavaScript projects with multiple packages.
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.
Lerna 是一个管理多个 npm 模块的工具,是 Babel 自己用来维护自己的 Monorepo 并开源出来的一个项目。优化维护多包的工作流,解决多包互相依赖且需要手动维护多包发版问题,其优点如下:
- 扁平:同一仓库下,统一管理维护多个 package
- 集中:在根目录的 node_modules/ 文件夹下维护所有的 package 的三方依赖
- 简化:根据文件变动统一执行命令,按需发包,自动升级版本并回写仓库、打 tag
- 高效:有互相依赖的项目可直接关联,避免开发人员在多仓库之间切换
Lerna 已被很多项目使用,如:React、Vue、Angular、Ember,Jest等,接下来我们将从0到1构建一个基于 Lerna 的 Monorepo 项目,并实现跨项目组件共享
三、项目构建
第一步:初始化项目结构
a. 安装 Lerna
npm install lerna -g
// 或者
yarn global add lerna
b. 新建目录并初始化
mkdir monorepo-demo
cd monorepo-demo
lerna init --independent
Lerna 初始化的时候,追加了一个 --independent 参数,其含义是使用独立模式
在 Lerna 中,有两种模式:
- 固定模式: 所有 package 版本号保持一致,每次更新发包都是全量的
- 独立模式: 每个 package 版本号各自独立,互不影响,每次更新按需发包
c. 新建子项目
lerna create common
npm init vue@latest
common:共享业务组件
a项目:projectA
b项目:projectB
第二步:安装依赖包&清理依赖包
多个项目有相同依赖时,会在对应的 package 安装相同的包,出现重复安装问题,于是,我们使用 --hoist 把每个package里的依赖包提到工程根目录,来避免重复安装问题
lerna bootstrap --hoist
再执行 lerna clean 来清除子项目里的包
learn clean
每次命令都需要输入 --hoist 比较麻烦,这里推荐在 lerna.json 里配置
{
"command": {
"bootstrap": {
"hoist": true
}
}
}
这里依赖包提升,如果遇到同一个包不同的版本,会提升用的最多的版本,这样会出问题,所以,我们用 yarn workspace 来提升相同版本的包,不同版本的包还在各自的目录,不做提升
// 顶层package.json
{
"workspaces": [
"packages/*"
]
}
//lerna.json
{
"npmClient": "yarn",
"useWorkspaces": true
}
c. 启动项目
每次启动都要去到对应的项目里执行命令,比较麻烦,这里我们可以在工程在外层 package.json 增加对应项目的启动命令,这样就不用切换目录来启动项目了
"scripts": {
"start:aSite": "lerna --scope @mono-repo-demo/projecta run dev",
"start:bSite": "lerna --scope @mono-repo-demo/projectb run dev"
}
通过 yarn start:aSite 即可启动 a 项目
d. 创建公共组件
// common/QtCard.vue
<template>
这是个公共组件
</template>
引入公共组件
lerna add @mono-repo-demo/common --scope @mono-repo-demo/projecta
a 项目引入
// projecta/App.vue
import QtCard from '@mono-repo-demo/common/components/QtCard.vue'
<qt-card></qt-card>
通过 learn public 命令发布,实际上也是 npm 发包,所以需要 npm login 登录一下 npm
至此,我们已经实现了最基本的 基于 Learn 的 monorepo 管理发布项目及包,还有很多东西值得我们去探索,比如 commitlint 配置、自动生成发包日志、编译压缩等,后期有时间我们将继续探索 Lerna的最佳实践
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK