从Lerna到Turborepo:shadcn/ui双components.json教你做大仓治理

目录


一、引言:Lerna 一年,我踩过的坑

先交代一下背景:我在一家金融科技公司做 KMS 知识管理平台的前端开发,技术栈是 React 18 + TypeScript + Ant Design + MobX,代码仓库用 Lerna 管理 Monorepo 已经一年多。

起初选 Lerna,是因为它"开箱即用"——lerna init 一把梭,lerna bootstrap 自动 link 依赖,lerna run build 串行跑所有包的构建。对于一个只有三四个包的 Monorepo 来说,这些足够了。

但随着业务膨胀,问题接踵而至:

痛点一:构建速度越来越慢。 五个包变成十五个包后,每次 lerna run build 要等 3-5 分钟。更致命的是,Lerna 默认按字母顺序串行构建,哪怕包 A 和包 B 毫无依赖关系,也得一个一个来。

痛点二:依赖提升(hoisting)带来的幽灵依赖。 Lerna 默认把子包的依赖提升到根 node_modules,导致 package.json 里没声明 dayjs,代码里却可以 import dayjs from 'dayjs'——这在本地跑没问题,一上 CI 就炸。

痛点三:任务编排能力弱。 你没法声明"包 C 的 test 依赖包 A 的 build",只能手动 lerna run build --scope=@kms/shared && lerna run test --scope=@kms/web,脚本越写越长。

痛点四:增量构建缺失。 改了一行注释,整个仓库重跑一遍构建,缓存形同虚设。

这些都是 Monorepo 规模扩大后的典型困境。恰好,shadcn/ui 最近发布了它的 Monorepo 模板,其中用 Turborepo + pnpm workspace 实现了非常精巧的架构设计——特别是"双 components.json"的配置模式。本文就以 shadcn/ui 的项目布局为案例,手把手拆解大仓治理的核心思路。


二、shadcn/ui 的双 components.json 设计拆解

2.1 先看项目结构

shadcn/ui Monorepo 模板的项目结构大致如下:

my-turborepo/
├── apps/
│   └── web/                          # Next.js 应用
│       ├── components.json           # ← 第一个 components.json
│       ├── package.json              # depends on @workspace/ui
│       ├── next.config.ts
│       └── src/
│           └── app/
│               └── page.tsx          # import { Button } from '@workspace/ui'
├── packages/
│   └── ui/                           # 共享 UI 组件包
│       ├── components.json           # ← 第二个 components.json
│       ├── package.json              # name: @workspace/ui
│       └── src/
│           ├── components/           # shadcn CLI 写入目标
│           │   └── ui/
│           │       └── button.tsx
│           ├── lib/
│           │   └── utils.ts          # cn() 工具函数
│           └── styles/
│               └── globals.css       # Tailwind CSS 全局样式
├── packages/
│   ├── eslint-config/
│   └── typescript-config/
├── pnpm-workspace.yaml
├── turbo.json
├── package.json                      # 根 package.json
└── sync-templates.sh                 # 模板同步脚本

2.2 两份 components.json 各司其职

shadcn/ui CLI 工具(npx shadcn@latest add button)在安装组件时,会读取当前目录下的 components.json 来决定:

  • 组件写入哪个目录
  • utils 导入路径怎么拼
  • Tailwind CSS 配置文件在哪

在这个 Monorepo 里,你有两份 components.json,每份的职责完全不同。

apps/web/components.json —— 应用的"消费视角":

{
   
   
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
   
   
    "config": "../../packages/ui/tailwind.config.ts",
    "css": "../../packages/ui/src/styles/globals.css",
    "baseColor": "zinc",
    "cssVariables": true
  },
  "aliases": {
   
   
    "components": "@/components",
    "utils": "@workspace/ui/lib/utils",
    "ui": "@workspace/ui/components",
    "lib": "@workspace/ui/lib",
    "hooks": "@workspace/ui/hooks"
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值