V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
BeijingBaby
V2EX  ›  程序员

Monorepo 就是个大坑

  •  
  •   BeijingBaby · 3 小时 45 分钟前 · 940 次点击

    让你陷入无限折腾中。

    monorepo 听起来很美好,多个项目作为子包放在同一个 repo 中,一般常听见的优点有:

    1 、一次打开所有项目,尤其是一个人需要修改或维护多个项目(子包)时,不用来回切换编辑器,很直观。

    2 、子包共享代码,如代码质量相关的 eslint 、prettier 、或跨 package 的代码等都可以给其他 pkg 的共享。

    3 、类型共享,如前后端都是 ts 所写,则 types 可以共享不用重复定义或者担心迭代中产生不一致。

    4 、ci/cd ,可以统一为整个 repo 做 ci/cd ,不再分散增加心智负担。

    但是,monorepo 会给你带来无限的折腾。

    首先,如果是跨语言的 mononrepo ,不同语言有不同的编码规范,根本不存在相同的 lint 或 prettier 。ci/cd 也相当于是独立项目要单独做,共享配置在这里没有带来任何好处的提升。

    其次是,即使你是相同语言的 monorepo ,前期在项目架构时候也会让你消耗很多精力。

    你需要创建 packages/prettier-config, packages/eslint-config...等等共享配置。

    每次创建一个其他 package 你需要修改配置文件使用这些共享配置。

    另外就是不同子包有不同的 eslint 配置,如 nextjs 和普通的 reactjs 项目就有不同的配置,你要么在 eslint-config 中再来一份针对 nextjs 的配置,然后修改 apps/web 引用,要么就干脆直接继承 eslint-config 再扩展 nextjs 官方推荐的配置。

    这个过程非常折腾,本身 nextjs 这类项目就是开箱即用,已经有合适的 eslint 配置,你非要提取到共享的 package 中,可能大多数情况你的 monrepo 就不存在多个 nextjs 项目共享配置的情况!

    好了,此时再来一个 nestjs 作为后端 api ,还得再折腾一遍 prettier-config ,eslint-config ,毕竟你都共享配置了,必须得用不是吗?

    直接把这些项目的开箱即用抛弃了。

    然后你的项目中要用 tailwind 或者 shadcn-ui ,你就会重复以上步骤,陷入无限的配置折腾中。

    另外就是权限怎么管理,你总不想任何人都有整个 monorepo 的代码权限吧?实习生来几天直接给你代码拷走了。

    multirepo 有问题吗?

    其实一点问题都没有,更好的权限权利,更内聚。

    一些项目本身开箱即用,创建好就能开始写业务,不用折腾什么共享配置。

    或者每个项目有一些重复代码也没有任何影响,存储空间又不费钱,但是更内聚了。

    要是有需求多个 repo 代码共享,统一标准,一样可以发布私有 npm 包来实现。

    项目迭代中某个 repo 重构或者换语言,都根本不用考虑其他 repo ,只要对外接口保持一致就行。

    个人感觉 monorepo 带来的提升很有限,不知道 v2er 的项目用的多不多,都用在什么场景?

    20 条回复    2025-09-16 22:39:46 +08:00
    JoeJoeJoe
        1
    JoeJoeJoe  
    PRO
       3 小时 40 分钟前
    我都是使用 vscode 的工作区来管理同一个项目里面不同的子项目, 好在 flutter 和 unity 都支持在 vscode 中直接调试.

    CHTuring
        2
    CHTuring  
       3 小时 39 分钟前   ❤️ 1
    用 monorepo 不一定要去折腾共用 prettier 或者 eslint ,这个放在各个 package 里设置 root 就可以了,这样世界不就很美好了
    kabob
        3
    kabob  
       3 小时 37 分钟前 via iPhone
    我觉得你有点钻牛角尖了,本身就是为了共享公共模块的,子包和子包如果规范不同没必要非得抽离出来,有点拿着锤子找钉子的意思了
    COW
        4
    COW  
       3 小时 27 分钟前
    是否遵循了约定大于配置的原则? Monorepo 通常是用于微服务场景,多语言是否有统一依赖或相互协作的强需求? CI/CD 与是否 Monorepo 关系不大,但是 repo 过多,运维复杂度会飙升,反而在一个仓库中结合 Jenkinsfile + Makefile 很好做统一管理。
    WenhaoWu
        5
    WenhaoWu  
       3 小时 23 分钟前 via Android
    Monorepo 还好,git submodule 这位才是重量级
    COW
        6
    COW  
       3 小时 13 分钟前
    @WenhaoWu 在需要定期跟踪同步第三方代码,但又不能 vendor 进自己 repo 的场景下,submodule 就非常好用,比如 hugo themes ,很典型的场景。
    wunonglin
        7
    wunonglin  
    PRO
       3 小时 7 分钟前
    风格这些完全不需要公共的。
    PainAndLove
        8
    PainAndLove  
       3 小时 6 分钟前
    Monorepo 适合拿收益,拿完赶紧跑 😁
    perfectlife
        9
    perfectlife  
       2 小时 39 分钟前 via Android
    别的不说,给 monorepo 做 cicd 真的是十分钟头疼,之前公司使用 mpnorepo 把安卓 ios 前端 的项目都塞在一个仓库下,cicd 一点都没有优雅可言,好多只能写死
    dssxzuxc
        10
    dssxzuxc  
       2 小时 31 分钟前   ❤️ 4
    去搞跨语言 monorepo 的懒得评论,属于没事找事,我就默认是 typescript monorepo

    packages/eslint-config packages/prettier-config
    这是错误做法,在新版本 eslint 中,一个 monorepo 应当只有一个 eslint.config 和一个 prettier.config ,它们覆盖所有要 lint 的文件,新版本扁平化配置文件能精细地针对不同文件,不同包,不同场景进行定制配置,旧版本这种到处塞屎的做法已经过时了,共享配置用得好那很好,但是多数人用不好,写得一坨狗屎,应该让最有经验的那人认真写一份集中配置,然后慢慢改进。
    所有配置遵循最小化原则,像 prettier 就没几条是需要配置的,默认配置已经很好了。
    尽量使用适合团队的 recommended 规则,然后在此之上进行小幅改动,能不改就最好不改。
    如果团队个个都是体操大师,请选择 strictTypeChecked+stylisticTypeChecked ,如果只想凑合过过日子,那就降级成 recommendedTypeChecked ,觉得 lint 太花时间就换 strict ,断言选手太多了 recommended 也不是不行。
    每个热门项目一般都有积极维护的 eslin 推荐配置,真正要自己配置的规则,其实最多也就几十条,再多那一定是因为各种历史原因堆积下来,维护者没时间去看默认配置的变更,很多开源项目就是这样,推动 lint 迭代比写代码还难,主要是性价比太低。
    同上所述,tailwind/unocss 等等东西的配置文件也应该只有一份,一定需要分开的只有 packag.json 、tsconfig.json

    权限管理?代码是世上最不值钱的东西,不会以为自己写出来的东西很宝贵吧?值钱的只有能赚钱的业务,这玩意是 copy 不了的。

    Monorepo 不是大坑,屎山才是大坑。
    imvkmark
        11
    imvkmark  
       2 小时 25 分钟前
    @JoeJoeJoe 你的图咋传的, Pro 才有的权限 ?
    Torpedo
        12
    Torpedo  
       2 小时 20 分钟前
    个人觉得 monorepo 能火,本质就是通过 monorepo ,解决版本管理对多项目管理的不足
    dssxzuxc
        13
    dssxzuxc  
       2 小时 10 分钟前   ❤️ 2
    最重要的是,lint 一定要持续升级,如果以任何理由拒绝 lint 的升级,那项目引入 lint 没有任何意义。
    lint 升级会强迫维护者重构自己代码,会暴露出隐藏起来的运行时隐患,升级 lint 不会破坏代码行为,只会破坏流水线,流水线不是用来看的,连 lint 都不升级那可能对代码行为产生破坏的依赖就更不会升级,那整个流水线也没多大意义,费心搞基础建设,结果不强制推动迭代,那一开始就别搞,一地鸡毛。
    renmu
        14
    renmu  
       2 小时 0 分钟前 via Android
    monorepo 对开源项目来说就是很大程度上加大了版本管理的心智负担,整体觉得还是利大于弊的
    weiwenhao
        15
    weiwenhao  
       1 小时 58 分钟前
    原来把多个项目放到一个仓库的方式叫 monorepo, 第一次知道这个名词。 我今天刚好做了这样的事情,因为受不了 git submodule ,然后多个仓库 issue 管理起来麻烦,并且对子仓库的贡献不能很好的体现在核心项目中。
    tonytonychopper
        16
    tonytonychopper  
       1 小时 38 分钟前
    @imvkmark 搞个 V2EX polish 插件
    mark2025
        17
    mark2025  
       1 小时 36 分钟前
    @weiwenhao 别用 git submodule ,太麻烦了。monorep 好得多
    Pipecraft
        18
    Pipecraft  
       1 小时 34 分钟前
    @imvkmark #11 imgur 的图片就可以。很多 V2 扩展或油猴脚本支持上传图片。
    seth19960929
        19
    seth19960929  
       1 小时 4 分钟前
    monorepo 只做单语言的, 多语言的干嘛用这个
    seth19960929
        20
    seth19960929  
       52 分钟前
    @weiwenhao 两个作用不一样
    submodule 适合库分享, 比如共同的代码,比如配置读取, 日志类似的, 或者(内部的 SDK ),还有 proto 文件的共同定义+生成的代码文件
    monorepo 适合项目级别划分,比如项目里的 订单 / 用户 / 商城 / 广告系统 / admin , 我没说微服务(确实微服务很适合), 想要按模块划分项目也可以用 monorepo
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2566 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:32 · PVG 23:32 · LAX 08:32 · JFK 11:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.