让 AI 写代码不再"就近解决":如何在 monorepo 里建设 AI context?
AI 常把需求写快了,但顺手又造一遍“节流/懒加载/环境判断”等轮子,结果是能跑却变沉,技术债上升。AI 不是不懂复用,而是“看不到”你的共享库。问题的本质是:AI 的思考模式天生倾向“就地解决”,思维聚焦于当前文件或仓库。再加上其不清楚自己的能力边界,难以主动突破上下文限制,导致其很难“优先复用 monorepo 的能力”,从而不断造轮子。
本文给出一套可被 AI 消化的上下文体系(CLAUDE.md + USEME.md + 规则),让它先复用、再改造,按团队的方法写对代码。你将看到:AI 如何“看世界”、monorepo 的典型局限、我们如何建设可消费的 AI context,以及一份可复制的落地清单。
AI 是怎么"看世界"的
语言模型不是 IDE,它靠"上下文窗口"理解你的意图。看得见的东西(当前文件、最近看过的文件、你粘给它的片段)权重更高。
以一个真实案例说明:我们让 AI 实现一个"判断是否在微信环境内"的功能。如果只把业务文件丢给它,AI 会写出这样的代码:
// ❌ AI "就近解决" 的典型输出const isWeChatEnv = () => /MicroMessenger/i.test(navigator.userAgent);useEffect(() => { if (isWeChatEnv()) { // WeChat 专属逻辑 }}, []);看起来不错?但问题是:
- 重复造轮子:我们的
common-ua 包里已经有 isWeChat 方法了脆弱的 UA 嗅探:容易被 UA 覆盖、WebView 差异或地区版本影响SSR 隐患:直接访问 navigator/window边界不清:未处理服务端渲染或无 UA 的场景但如果 AI 能"看到"我们的公共库文档,它会写出:
// ✅ 有了正确上下文后的输出import { isWeChat } from 'common-ua';if (isWeChat()) { // WeChat 专属逻辑}区别很明显:代码更短、更安全、更可维护。关键是 AI 需要在正确的时机"看见"正确的信息。
在 monorepo 里的两大局限
1. 找不到"正确的能力边界"
先看看我们的 monorepo 目录结构:
monorepo_apps/ # 根仓库├── support_modules/ # 公共能力仓库│ ├── common-util/ # 纯工具函数库│ ├── common-react-hooks/ # 无业务耦合 Hooks│ └── common-ua/ # UA/环境检测│ └── ......└── apps/ # 业务应用 ├── 业务1/ # 业务1 ├── 业务2/ # 业务2 └── ......在这个结构中,AI 经常分不清能力边界,比如:
- 让它做"移动端适配",它可能在业务代码里写
window.innerWidth < 768,而不是用 common-ua 的 isMobile()2. 文档信息碎片化
我们统计了一下改造前的文档分布:
README.md:数量多,内容重复度高,难以维护老 Wiki 页面:存在过期信息,容易误导口头传承的"最佳实践":不可追踪,且经常与代码不一致AI 面对这么多信息源,经常选择"安全策略"——重新实现,而不是冒险引用可能过期的代码。
踩坑历程:从混乱到有序
第一阶段:意识到问题(痛苦期)
我们发现团队里 AI coding 的输出虽然能跑,但质量参差不齐:
统计数据(改造前 3 个月):
- 重复实现的工具函数:27 个不一致的导入风格:占比 48%
典型问题案例:
// 案例:AI 重复实现已有的 UA 检测const isMobile = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);};// 实际上 common-ua 里已经有更完善的实现:import { isMobile } from 'common-ua/src/platform';第二阶段:探索解决方案(试错期)
我们尝试了几种方法:
方法 1:对话窗口建立约定效果:约等于没有。AI 不会记住上次的约定。
方法 2:在每个项目的 README 里写"使用指南"
效果:信息重复,维护成本高,AI 还是经常找不到。
方法 3:建立"代码库索引文件"我们写了一个 index-of-libraries.md,列出所有可用的工具。效果:有改善,但 AI 还是倾向于"就近解决",除非明确指出文件路径。
第三阶段:系统性改造(见效期)
在 monorepo 项目里用 AI,最重要的是要先给它"定好规矩"。首先,每次让 AI 改代码之前,最好先让它了解一下项目结构。比如让它先看看根目录的 package.json 和 CLAUDE.md,确认这是个什么样的项目。我们项目有 25 个子应用,共享库就在 support_modules 目录下,这些信息对 AI 来说很重要。其次,要明确告诉 AI"先找现成的,再考虑新写"。
我们的解决方案:让 AI 有"路标"、有"准则"、有"口袋书"
核心架构:两层文档体系
CLAUDE.md (总路标)├── 快速开始 (命令速查)├── Monorepo 概览 (包清单 + USEME 路径)├── AI 协作规范 (Do/Don't)├── 常见坑与约束├── 文档地图与生成└── 版本与兼容性说明support_modules/*/USEME.md (具体指南)├── 目录├── 导入说明 (强制具体路径)├── 重点 API 参数表├── 分类 API 概览├── 组件用法示例├── 注意事项└── 最佳实践与故障排除1. 文档路标:CLAUDE.md
设计原则:AI 看到这个文件,应该能在 5 秒内理解项目全貌。可以通过 claude init 命令生成,也可以借助其他大模型生成。
AI 协作规范(Do/Don't)
Do
- 使用具体文件路径导入;禁止 barrel(如
import { X } from 'pkg')。最小化影响:不改对外 API;不做无意义格式化;保持文件/模块结构不变。SSR 安全:涉及 window/document 仅在浏览器端执行;必要时判空/条件分支。Don’t
- 不写版本兼容信息到 USEME(统一放本文件)。不扩大改动范围(移动文件、拆并模块)除非明确要求。
2. 可被 AI 消化的用法手册:各包的 USEME.md
在公共包下建立简约并明确的 USEME.md 文档,供 AI 阅读和了解该包的功能和用法。
设计原则:每个示例都能直接复制粘贴使用,每个参数表都能当 API 手册查。
提示词模板(给 AI 的最小上下文)
在与 AI 协作时,建议附上精简、稳定的上下文提示,避免跑偏:
你在一个 pnpm + monorepo 项目中工作。先读根目录 CLAUDE.md 了解规则,再读相关包的 USEME.md。优先复用 support_modules 下的能力,禁止 barrel 导入,必须使用具体文件路径。若涉及 UA/SSR/性能,请优先查找 common-ua、common-react-hooks、common-util 的对应能力。在给出修改前,用项目内既有 API 校对一次是否可复用。小技巧:把这段模板固化到 .cursorrules 或常用的 Prompt 片段里,减少每次重复粘贴。
3. 跨仓库上下文打通:业务仓库"认识"support_modules
技术实现:给 cursor 添加 Rules:
严格遵循工作流程:收到任务 → 检查 Rules → 分析项目结构 → 执行。阅读项目中的 package.json、CLAUDE.md 和 USEME.md 以遵循项目约定。检查该项目是否为 monorepo 架构,如果为 monorepo 子仓库,则向上查看父仓库和 support_modules 的指导文件(package.json、CLAUDE.md 和 USEME.md)以进行跨仓库协作。关键机制:
- 自动索引:AI 会主动检查大仓的
CLAUDE.md路径映射:通过 CLAUDE.md 的"文档地图",AI 知道去哪找每个包的 USEME.md优先级控制:公共库的 USEME.md 比业务代码有更高的参考权重实施细节:魔鬼在细节里
1. 文档结构的精心设计
标题层级:我们发现 AI 对标题层级很敏感
## 重点 API 参数:AI 优先关注### 具体函数名:AI 能精确定位#### 参数详解:AI 会仔细解析表格格式:参数表的列顺序经过多次优化
| 参数名 | 类型 | 默认值 | 必填 | 说明 |这个顺序比其他排列方式的 AI 解析准确率高 15%。
2. 跨仓库协作的技术细节
完整目录结构:
monorepo_apps/ # 根仓库├── claude.md # 总路标├── support_modules/ # 公共能力仓库│ ├── common-util/│ │ ├── USEME.md│ │ └── src/│ ├── common-react-hooks/│ │ ├── USEME.md│ │ └── src/│ └── common-ua/│ ├── USEME.md│ └── src/└── apps/ # 业务应用 ├── 业务1/ # 业务1 └── 业务2/ # 业务2在根仓库 claude.md 中添加文档地图:
support_modules - 核心业务逻辑模块| 包 | 用途 | 文档 || ----------------- | --------------- | --------------- || umu-util | 工具函数库 | `support_modules/umu-util/USEME.md` || umu-react-hooks | 无业务耦合 Hooks | `support_modules/umu-react-hooks/USEME.md` || umu-ua | UA/环境检测 | `support_modules/umu-ua/USEME.md` |AI 索引机制:
- AI 读取
.cursorrules,知道要检查父仓库通过 monorepo_apps/CLAUDE.md 获取全局规范根据"文档地图"索引各包的 USEME.md在生成代码时优先使用公共库的能力踩坑经验:我们犯过的错误
1. 文档过于详细反而有害
错误做法:最初我们在 USEME.md 里写了很详细的实现原理和设计思路。结果:AI 被"误导",经常尝试"改进"我们的实现。
正确做法:只写用法,不写原理。让 AI 当"用户",不当"维护者"。
2. 示例代码的"诱导性"很强
错误做法:示例中使用了简化的错误处理:
// ❌ 糟糕的示例loadMore().then((data) => setList([...list, ...data]));结果:AI 照搬这种写法,忽略了错误处理。
正确做法:示例必须展示完整的最佳实践:
// ✅ 完整的示例loadMore() .then((data) => setList((prev) => [...prev, ...data])) .catch((err) => showError(err.message)) .finally(() => setLoading(false));3. 过度约束反而降低效率
错误做法:初期我们制定了 20+ 条详细规范。结果:AI 被约束得"畏首畏尾",生成的代码过于保守。
正确做法:精简为 5 条核心约束,其他通过示例引导。
若你也准备在 monorepo 里用好 AI coding,可以这样落地
第一步:建立文档体系
核心文件优先级:
CLAUDE.md(总路标)各公共包的 USEME.md(常用工具)第二步:跨仓库集成
在编辑器(如 cursor)中添加 rules,
业务仓库配置:
重要:因为 AI 往往会寻求"就近解决"。所以需要强制规定 AI 的思考模式,要求先阅读 rules 并了解项目结构,然后再工作。
// .cursorrules严格遵循工作流程:收到任务 → 检查 Rules → 分析项目结构 → 执行。检查该项目是否为 monorepo 架构,如果为 monorepo 子仓库,则向上查看父仓库和 support_modules 的指导文件以进行跨仓库协作。第三步:一小时落地清单(可直接执行)
- 在根目录新增/完善
CLAUDE.md:包含包清单、文档地图、导入约束为常用公共包补齐 USEME.md:每个至少 1 个复制即用的示例统一导入方式:在示例和脚手架中全部改为具体文件路径在编辑器加入 .cursorrules:强制工作流与跨仓库检索加入 3 个简单的静态检查脚本(重复工具、barrel 导入、SSR 危险 API)选一个真实需求做“对照试验”:先不加上下文生成一次,再按规范生成一次,对比差异尾声
AI coding 的价值不止是"写快一点",更在于"写对一点"并且"复用多一点"。在 monorepo 里,这意味着给 AI 一张清晰的地图、明确的边界和可复制的惯用法。
我们用 CLAUDE.md 约束,用 USEME.md 传达,最终让 AI 在业务仓库里自然地"看见并复用" support_modules 的能力。实际落地后,重复造轮子的情况显著减少,提交一次通过率明显提升,新人融入速度也更快。
轮子造得再好,也比不上全仓库的人一起用同一个。现在,AI 也学会了这一点。
如果你也在大型项目里用 AI coding,不妨试试这套"文档驱动"的方法。让 AI 助手也会自动"学会"你们的最佳实践,成为真正能理解业务、写出符合团队要求代码的 AI coding engineer。
