当前位置:网站首页>Monorepo管理方法论和依赖安全
Monorepo管理方法论和依赖安全
2022-07-05 20:38:00 【咲奈】
前言
最近看到、体验了不少 不规范 的 monorepo 仓库和场景,有很多错误点,都和我自身曾经的失败经历都如出一辙,因为他们最后都会、很快就会变成不可逆的历史债务。
为了避免历史债,现代 monorepo 的一些行为、规范底线是什么?
正文
使用最新版本的 pnpm
由于存在依赖提升、幽灵依赖问题,目前的唯一且最佳解只有 pnpm ,关于选型临界点,可参考:
同时,应该使用最新版本的 pnpm (现在是 v7 ),如果你目前正在使用 v6 ,可参考:
在配置上, pnpm v7 对 peer deps 的默认严格设定需要如下选项解决:
# .npmrc
strict-peer-dependencies=false
详见 pnpm > .npmrc > strict-peer-dependencies 。
另外,为了应对突发情况,常常需要 pnpm.overrides 等选项加以辅助,比如被供应链攻击时要统一全局某个依赖的版本:
// package.json
{
"pnpm": {
"overrides": {
"some-dep": "1.0.0"
}
}
}
使用 pnpm monorepo 管理
每个项目都会有膨胀的趋势,意味着单体设计不再符合现代 FE 项目发展方法论。即使是单包应用也应该使用 monorepo :
SDK :对于 sdk 项目,未来需要拓展必然面临 monorepo 分包解耦,且本地测试、调试需要 example 项目,通过 pnpm 的
workspace:*
协议链接 sdk 子包可以很好的支持即时修改来调试,彻底避免 link 繁琐、不好用问题。Project:对于业务项目,未来必然面临项目膨胀需要抽取复用的情况,所以 monorepo 设计是必然,否则将面临项目整体移动大整改和多个仓库需要反复发包修改版本号的痛苦成本。
仓库初始设计是非常重要的,他决定了你的项目未来一直要保持的一种状态,从一开始就应该面向远景,而不是遇到了再解决,否则移动全部文件破坏 commit history 不说,还会因为很多路径因素等固有的历史债形成无法逾越的发展阻碍。
monorepo 全局不安装依赖
要谨慎对待 monorepo 的顶层,因为顶层依赖会被所有子包共享到,形成隐形的幽灵依赖,并且很难被察觉:
- 除了
npm-run-all
、cross-env
、自建的 script 脚本包等仅用于本地开发环境的工具依赖,应该极力避免在顶层安装任何生产依赖。
一时顶层一时爽,项目报错怎么都找不到原因,切记不要滥用顶层,否则会造成不可逆的历史债。
使用其他子包必须放到 dependencies 里
在一个子包里需要使用其他子包代码时,必须要把它加到 package.json#dependencies
里,使用 workspace:*
协议链接:
// package.json
{
"dependencies": {
"@scope/some-dep": "workspace:*"
}
}
注:切记不要将该包安装在全局,否则多人协作下久而久之就会产生幽灵依赖、版本不一致等不可逆的历史债。
使用 type 检查
确保你的仓库中没有非人为的 type 错误:
SDK:对于 SDK 项目,应该在 测试环节 / CI 中使用
tsc --noEmit
进行全仓的 type 检查。Project:对于业务项目,除了可以使用
tsc --noEmit
外,还可以使用fork-ts-checker-webpack-plugin
该 webpack 插件来在编码阶段规范行为。
这可以大大减少错误、不稳健的编码,并且防止使用了不存在的依赖导入。
使用 workspace:* 协议关联子包
子包间相互引用代码时,应该使用 workspace:*
的写法来链接子包,而不是具体的版本号,这可以防止多人协作时修改版本的遗漏和冲突。
如果有发包场景,应该使用 changesets 来发包,该工具会帮你自动升级版本、产生 CHANGELOG 、自动替换 workspace:*
为具体版本、自动保持版本一致性,对标最佳实践。
关于 changesets 的基础内容可自行搜索学习,进阶内容可参考:
使用 turborepo 避免循环依赖
在构建子包时,为了达到按需、最优的构建路径,应该使用 turborepo 定向构建,turbo 会自动帮你检查有无循环依赖,若有会报错退出。
需要注意的是 pnpm 原生支持的定向构建 pnpm -r --filter
检测不到循环依赖。
另外,由于 turbo 执行命令不方便携带额外参数(一个经典的场景是本地构建需要包的 declarationMap
方便定位,而云不需要),所以可以编写一个脚本判断 process.env.CI
是否存在(需要构建环境的镜像支持该变量),然后本地用 pnpm -r --filter
构建预依赖,云用 turbo 构建。
关于 turborepo 的相关参考可见:
分包思维、多解耦子包
拆分思维
既然使用了 monorepo ,具有天生的解耦优势,就不应把内容做成一个巨石单体,应该多拆分子包,尽量把公共部分提取出来复用。可以分领域来做,解耦程度越高,越不容易产生循环依赖和循环引入,项目更清真。
对于抽取后引用代码包的热更新问题需要用 monorepo 重定向来解,详见:
注:业务项目还是要有度抽离,毕竟你不做 也迟早会被别人加 ,不要追求极致复用。
领域思维
应该多开 workspace 文件夹,分领域管理,而不应该在全局上加 ,比如:
apps/*
:该文件夹下全放业务项目。libs/*
: 该文件夹下全放 sdk 和复用组件。templates/*
:该文件夹下放模板项目。configs/*
:该文件夹下全放eslint
/tsconfig
等公共配置的子包。
示例:
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'examples/*'
- 'libs/*'
- 'configs/*'
- 'templates/*'
- 'scripts'
# ...
比如有文档站,配置共用的情况,应该全部做成子包,而不是在全局上加文件,否则会产生巨大的历史债务。
注:所有的项目都应该是子包,不要顶层 root 是一个项目,还开了 workspace ,不光全局依赖会影响子包,还会导致不可逆的历史债!
总结
正因为 monorepo 是一个未来可能会不断膨胀的蓝图愿景,所以各种规范和底线才格外重要,否则有一个 “错误要素” ,很快所有协作者都会沿用、繁殖下去,导致整个项目的毁灭。
关联阅读
边栏推荐
- Informatics Olympiad 1340: [example 3-5] extended binary tree
- 本季度干货导航 | 2022年Q2
- [UE4] unrealinsight obtains the real machine performance test report
- Kubernetes resource object introduction and common commands (V) - (configmap & Secret)
- Classic implementation of the basic method of intelligent home of Internet of things
- Applet global configuration
- Simple understanding of interpolation search
- CTF逆向基础
- Duchefa丨MS培养基含维生素说明书
- 【刷题记录】1. 两数之和
猜你喜欢
Duchefa MS medium contains vitamin instructions
Rainbond 5.7.1 支持对接多家公有云和集群异常报警
ProSci LAG3抗体的化学性质和应用说明
Abnova丨DNA 标记高质量控制测试方案
Abnova丨CRISPR SpCas9 多克隆抗体方案
如何形成规范的接口文档
表单文本框的使用(二) 输入过滤(合成事件)
2.8、项目管理过程基础知识
Scala basics [HelloWorld code parsing, variables and identifiers]
[Yugong series] go teaching course in July 2022 004 go code Notes
随机推荐
ROS2专题【01】:win10上安装ROS2
Classic implementation method of Hongmeng system controlling LED
Abnova丨E (DIII) (WNV) 重组蛋白 中英文说明书
Abnova 环孢素A单克隆抗体,及其研究工具
Duchefa丨P1001植物琼脂中英文说明书
When JS method passes long type ID value, precision loss will occur
Leetcode (347) - top k high frequency elements
Leetcode (695) - the largest area of an island
2022北京眼睛健康用品展,护眼产品展,中国眼博会11月举办
【愚公系列】2022年7月 Go教学课程 004-Go代码注释
1、强化学习基础知识点
常用的视图容器类组件
Rainbond 5.7.1 支持对接多家公有云和集群异常报警
死信队列入门(两个消费者,一个生产者)
小程序项目结构
Rainbow 5.7.1 supports docking with multiple public clouds and clusters for abnormal alarms
【刷题记录】1. 两数之和
E. Singhal and numbers (prime factor decomposition)
Informatics Orsay all in one 1339: [example 3-4] find the post order traversal | Valley p1827 [usaco3.4] American Heritage
[Yugong series] go teaching course in July 2022 004 go code Notes