Monorepo设计思路(Speeches)

先言

This article is a speech

结构设计

位置作用
libs/*提供基础能力、框架、sdk、组件库等
apps/*业务应用(微前端子应用、整体应用)
核心,所有基础能力为业务服务
templates/*各种模板
utils/*赋能工具
.../*更多分类…

驱动模式

基础能力 - libs

领域范围
  1. sdk:埋点 / 环境变量 / 请求方法 / 高层封装工具等等…
  2. 组件库:表单 / 联动组件 / 复杂组件等等…
  3. 框架:业务自洽性,必要的黑盒、限制,缺省配置,收敛等…
  4. 等等…
技术范围
  1. tsc 、rollup、webpack 等打包工具
  2. 框架(swc 、esbuild、mfsu 等)
  3. 组件库的依赖
  4. 等等…
如何丝滑
支持 monorepo 引用热更新

monorepo redirect 思路定位到 src 源码支持热更新

解耦、可复用
  1. 多抽离,多分层
  2. 明确上下级链路调用、依赖关系
  3. 长远发展视角设计,向前兼容
解多重依赖

有几种定位依赖的策略、做法:

事项解法
重要依赖唯一定位框架帮助重定位重要 dep 位置,保持唯一性。
react / react-dom / react-router / react-router-dom / antd 等 alias 唯一定位,防多 hooks 问题
peerDeps 定位因为依赖会先用他文件夹内的 devDeps,违背了 npm 依赖的思维。
需不需要定位依赖的 peerDeps 解掉这个问题?
dependenciesMeta 定位重定位还是 dependenciesMeta 模拟真实 npm 包的行为?
建议重定位
其他符合场景的定位还需要定位哪些?
根据场景来

核心业务 - apps

全部场景覆盖。

领域范围
  1. 微前端设计

    i. 基座

    ii. 子应用:一个 平台 / 页面 作为子应用,能随处找坑插入,独立部署,独立工作流

  2. 不光是微前端

    i. 搭配 nginx / 网关 / cdn / nodejs 等实现非微前端应用的项目

技术范围
  1. qiankun
  2. react 、react-dom 等业务依赖
  3. 自由发挥、限制…
如何丝滑
减少不必要的代码
  1. 减少微前端初始化 runtime 、入口配置代码。如 umi 中间层
  2. 减少配置。默认好用,缺省最优,收敛、抽象配置方法到 lib 里。
  3. 减少依赖。如抽取组件来解,umi all in one 的思路等
初始化容易
  1. 让新项目 create 的轻且易,生成文件思路不限,如 cli 从云拉取 template 的最新版本 npm 依赖,再做必要的替换。
  2. 考虑 微前端、非微前端、组件库 等等多场景更好

其他支持 - templates / utils / …

领域范围

用 workspace dir 来分类的原则,存放你需要分类的事物。

如:

  1. eslint-config / plugin
  2. template
  3. 适应你场景需要的提效工具…
好处

在一套协作、发布流里,互相引用方便,可以同时更新发布,版本一致性等

坏处

东西多了造成冗余

顶层 - root

领域范围
分类解法
全局脚本发布脚本、规范化脚本、依赖操作脚本等
全局配置1. eslint / prettier / editorconfig 等是否需要一统?
一统后子项目无需再配,不一统自由度更高,可设计继承
2. tsconfig.base.json 等可最大程度复用的配置,多写点继承,少 copy
3. changesets / turbo 等等…
技术范围
  1. changesets 发布流
  2. turborepo / pnpm filter 构建流
  3. zx 等常用支持工具
如何丝滑
配置收敛多少

根据场景来,比如有组件库的 tsconfig.base ,有业务项目用的 tsconfig.app,多玩继承。

必要的全局依赖

评估好哪些需要提升到全局,好处是只升级一处就可以,否则要跑到无数子项目 package.json 里去打苦工。
比如从以下视角出发价值判断:

  1. 开发依赖rimrafzxchalk 等开发用依赖提升风险小,收益高
  2. 组件库等antdicons 库、业务依赖 等业务生产依赖提升需思考,但业务项目可以自己再装自己的,需斟酌。
  3. 核心依赖reactreact-dom 等,是否需要提升?根据情况来
  4. 应用经验lodash 等库,常年不变动,放心提升
选择总 lock 还是分 lock

pnpm lock file 可以在全局,也可以在单独项目中。

位置好处坏处
全局 lock最大程度复用,节省空间,安装速度快,一次即可搞定 all 项目安装了一些不必要的依赖,每次提交影响全局 lock 文件起冲突
(好在 pnpm 处理 lock 文件的能力很强大,可以不提交 lock 找机会集中去 update)
分项目 lock互相改动依赖不影响其他人,不会起冲突依赖复用性差,每个项目都要执行 install script hook ,core-jsswc等大量库都有这个环节,速度奇慢无比
(pnpm 有选项来缓存 script 的结果,但第一次是否忍)

在本文的设计场景中,因存在先置依赖,需要直接用产物,所以只能取全局 lock ,在 install 结束后,要预构建出必要的支持产物,再启动 app 中的 project。

构建流

每个 app 的 package.json#name 都遵守统一的格式,如:@scope/project-${app-id}

在构建时根据 id 注入环境变量,执行 turbo 最优顺序构建时,按照 name 格式拼接起来作为 --scope 值即可定点完成任务。

注:如果是自动 trigger 类的 cicd ,可以通过 webhook 等 api 识别 merge 进来的文件在哪个 path 下解,比如可以把 app id 也作为文件夹名,看看 change 到了哪个文件夹就知道哪个 app 要 build 了。

发布流

注意 changesets 还是会给 private: true 的子包( 比如 app 业务项目要限制 )生成 CHANGELOG 文件的,只有加入到 changeset 配置文件的 ignore 列表里才不会有这个冗余情况。

这里可以在发布的先置阶段,用 workspace 工具扫描然后自动填到 ignore 列表里来解。

设计思考

结构合理、庞大性

trade off。

把框架放在仓库是否冗余了,去掉?
  • :运行 app 不用先构建出来框架的产物了
  • :不能即时得到最新变动 、fix 的收益
把全部 libs 分到其他 monorepo 仓库?
  • :纯业务仓库,领域清真
  • :要从 npm 下载,没有 workspace:* 的即时引用,即时修改的敏捷开发好处了,当然分离多少是个 trade off。

仓库庞大性

trade off。

支持派
  1. 都放在一起,业务领域一览无疑,不用到处跳 repo,交接、新人学习成本低,互相复用真爽
  2. 即时改动,即时热更新,可以享受到最新的变动
  3. depth=1 ,删除分支,静态资源提前上云 等减小仓库体积
  4. facebook 等厂均是单仓主干开发
反对派
  1. 冗余成本
  2. 随着发展仓库体积增大,拉取速度慢
  3. 业务领域不清晰,混杂不清真

资源分享

pnpm
changesets
turborepo

以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值