惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
Last Week in AI
Last Week in AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
J
Java Code Geeks
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
月光博客
月光博客
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
B
Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
美团技术团队
Y
Y Combinator Blog
T
Tailwind CSS Blog
宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
B
Blog RSS Feed
V
Visual Studio Blog
MyScale Blog
MyScale Blog

博客园 - 丁少华

adb提取本机apk 安卓ADB调试安卓 高德地图车机版本9.5制作共存 Taskfile 拆分子文件 go项目的taskfile Go 内嵌网页 windows的终端像mac一样好用 pgsql指定用户看到某个表 vue不使用根组件 Huma + Orval 前后端 API 自动生成方案 Mac安装nginx 不喜欢Go的几点 代码写错分支拯救指南 React UI 库推荐 Loop Engineering Vue 3 UI 组件库 Neon白嫖免费pgsql 域名利用cloudflare免费图床 nginx反代CloudflarePages提示502 vite使用shadcn vite使用biome Window下Nginx winserver2022安装不上软件 mac已损坏无法打开 代码高亮 命令运行器之task 命令运行器之just windows开启wsl 白嫖Redis 白嫖MongoDB
monorepo前端专属吗
丁少华 · 2026-01-03 · via 博客园 - 丁少华

打破误解:Monorepo 不只是前端专属,后端早已玩得炉火纯青

引言

搜索“Monorepo”,铺天盖地都是 pnpm、Turborepo、前端组件库的内容,很容易让人产生一个错觉:Monorepo 是前端专属架构模式。作为一个全栈开发者,我曾长期抱有这样的误解,直到深入研究了各个语言生态后,才发现真相完全不同。

今天,我要分享三个关键洞察:

  1. 所有主流语言都支持 Monorepo,只是实现方式不同
  2. 后端用 Monorepo 的历史比前端更悠久
  3. 搜索偏差背后的技术文化差异

一、各语言如何实现自己的“Workspace”

首先回答最实际的问题:没有 package.json,其他语言怎么搞 Monorepo?

1. Java - Maven 多模块项目

<!-- 根目录 pom.xml -->
<project>
    <groupId>com.company</groupId>
    <artifactId>monorepo-root</artifactId>
    <packaging>pom</packaging>  <!-- 关键:pom 类型 -->
    
    <modules>
        <module>libs/common</module>
        <module>services/user-service</module>
        <module>services/order-service</module>
    </modules>
</project>

Maven 通过 <modules> 标签定义多模块,子模块自动继承父级依赖版本,这其实就是 Java 版的“workspace”。

2. Go - Workspace (Go 1.18+)

# 初始化工作空间
go work init
go work use ./services/user-service
go work use ./libs/common

# go.work 文件内容:
go 1.21
use (
    ./libs/common
    ./services/user-service
)

Go 1.18 正式引入 Workspace 特性,允许在单个仓库中管理多个模块,解决了本地开发时的模块替换问题。

3. Python - Poetry Workspace

# pyproject.toml (根目录)
[tool.poetry.workspace]
members = [
    "libs/*",
    "apps/*",
    "services/*"
]

# 子项目引用本地依赖
[tool.poetry.dependencies]
common-lib = { path = "../../libs/common", develop = true }

Poetry 的 workspace 功能与 pnpm workspaces 异曲同工。

4. 跨语言终极方案 - Bazel

# BUILD.bazel 示例
java_library(
    name = "common",
    srcs = glob(["src/main/java/**/*.java"]),
)

go_binary(
    name = "user_service",
    srcs = ["main.go"],
    deps = ["//libs/common:go_default_library"],  # 跨语言依赖!
)

Google 开源的 Bazel 支持 Java、Go、Python、C++ 等多种语言,是真正的跨语言 Monorepo 构建系统。

二、概念映射表:前端术语 vs 后端术语

理解了各语言的实现方式后,我们来看这个关键映射表:

前端概念 Java 世界 Go 世界 Python 世界 通用术语
package.json pom.xml go.mod pyproject.toml 项目配置
pnpm workspaces Maven Modules Go Workspace Poetry Workspace 工作空间
node_modules ~/.m2/repository GOPATH/pkg 虚拟环境 依赖缓存
npm install mvn install go mod download poetry install 依赖安装
"common": "workspace:*" ${project.version} replace 指令 develop = true 本地依赖

核心洞察:每个语言生态都有自己的实现,只是语法不同,概念完全相通。

三、为什么你搜到的都是前端内容?

这是最有趣的部分。根据我的观察和数据分析,原因有三:

1. 术语“品牌化”效应

前端社区擅长创造和推广新术语,同样的概念:

  • 后端传统叫法:“多模块项目”、“复合构建”、“单一代码库”
  • 前端时髦叫法:“Monorepo”

就像“云原生”概念一样,很多技术早已存在,但新术语让它们重新受到关注。

2. 工具生态差异

// 前端:工具即产品,需要营销
{
  "Turborepo": "Vercel 的商业产品",
  "Nx": "Nrwl 的商业产品", 
  "pnpm": "开源但需要推广",
  "结果": "大量教程、博客、视频"
}

// 后端:工具即基础设施,低调务实
{
  "Bazel": "Google 内部工具开源",
  "Maven": "Apache 基金会项目",
  "Gradle": "开源但企业导向",
  "结果": "官方文档为主,营销内容少"
}

3. 社区文化差异

前端社区

  • 开发者活跃在 Twitter、掘金、个人博客
  • 喜欢分享新工具、新实践
  • SEO 做得好,内容容易被搜索到

后端社区

  • 更多在企业内部或专业论坛讨论
  • 关注稳定性而非时髦概念
  • 很多最佳实践存在于公司内部文档

4. 实际搜索数据佐证

查看 Google Trends 会发现:

  • “pnpm monorepo” 搜索量是 “java monorepo” 的 5 倍
  • “yarn workspaces” 搜索量是 “gradle composite builds” 的 8 倍

但这不代表后端用得少,只代表后端不这么叫。

四、现实中的 Monorepo 使用情况

大公司都在用,只是不说

  • Google:全球最大的单一代码库,使用 Bazel
  • Facebook:使用 Buck 管理所有代码
  • Uber:数千个 Go 服务在一个 Monorepo 中
  • Microsoft:VS Code 项目就是多语言 Monorepo

中小企业逐渐普及

# 现代全栈项目结构示例
fullstack-app/
├── apps/
│   ├── web/          # Next.js (TypeScript)
│   ├── mobile/       # React Native
│   └── admin/        # Vue.js
├── services/
│   ├── api/          # Go
│   ├── auth/         # Python
│   └── analytics/    # Java
├── packages/
│   ├── ui/           # 共享组件 (TS)
│   ├── schemas/      # 数据库模型 (多语言)
│   └── configs/      # 统一配置
└── infrastructure/   # Terraform, Docker

五、如何正确开始后端 Monorepo

1. 按语言选择工具

# Java 项目
推荐:Gradle Composite Builds
命令:gradle init --type java-library

# Go 项目  
推荐:Go Workspace (1.18+)
命令:go work init && go work use ./...

# Python 项目
推荐:Poetry + Poetry Workspace
命令:poetry new --src my-package

# 多语言混合
推荐:Bazel 或 Nx

2. 渐进式迁移策略

不要一次性重构成 Monorepo,而是:

  1. 先提取共享库到独立模块
  2. 配置本地依赖引用
  3. 统一构建脚本
  4. 最后考虑完整 Monorepo 工具

3. 搜索时用对关键词

别再只搜“Monorepo”,试试:

  • “maven multi-module best practices”
  • “go workspace microservices”
  • “bazel tutorial for beginners”
  • “large scale code organization”

六、写在最后

Monorepo 本质上是一种代码组织哲学,而不是某个特定工具或语言的特性。它解决的核心问题是:

  1. 代码共享:避免重复造轮子
  2. 版本一致性:确保依赖版本统一
  3. 原子提交:跨模块变更一次提交
  4. 统一构建:简化 CI/CD 流程

前端社区让这个概念变得流行,但后端世界早已在实践中深耕多年。下一次当你看到“Monorepo”时,请记住:

  • 它不依赖于 pnpm 或 package.json
  • 每个主流语言都有自己的实现
  • 大公司后端用它管理数百万行代码
  • 关键是理念,不是具体工具

希望这篇文章能打破你的信息偏差,让你在全栈开发中更加游刃有余。毕竟,好的架构思想应该是语言无关的。


扩展阅读

  1. Google 的单一代码库实践
  2. Bazel 官方文档
  3. Go Workspace 提案
  4. Maven 多模块指南

欢迎在评论区分享你的 Monorepo 实践经验,无论是前端、后端还是全栈项目!