十条经过实战检验的 TypeScript monorepo 约定

点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群

十条经过实战检验的 TypeScript monorepo 约定 —— 覆盖命名、TS 配置、project references、构建、发布、测试与边界控制 —— 让代码库能够在时间中稳定扩展。

Monorepo 在最初总是让人感觉非常顺滑 —— 但六个月后就会变得一团糟。秘诀不在于炫技的工具链,而在于一小套朴素但持久的约定。下面这十条约定能够帮助团队持续交付,不再出现“谁又把什么弄坏了?”这种戏码。说实话,未来的你一定会感谢现在的你。


1)按业务域命名,而不是按技术层命名

使用业务语言(auth、billing、search),而不是技术层(utils、helpers)。这会促使更清晰的边界划分,也更容易确定归属。

apps/ web/ worker/packages/ auth/ billing/ search/ ui/

为什么能长期有效:业务域可以经得住重构,而技术层不会。


2)统一使用 workspaces + workspace: 协议

选择一个工具(我偏好 pnpm,因为速度快且更严格),并用workspace:*来明确本地依赖,同时避免版本耦合。

// package.json (root){ "name": "@acme/monorepo", "private": true, "packageManager": "pnpm@9.0.0", "workspaces": ["apps/*", "packages/*"], "scripts": { "build": "pnpm -r build", "test": "pnpm -r test" }}// apps/web/package.json{ "name": "@acme/web", "dependencies": { "@acme/auth": "workspace:*", "@acme/ui": "workspace:*" }}

为什么能长期有效:不会意外发布半成品版本,也不会造成同级包之间的 semver 漂移。


3)使用一个严格的 tsconfig.base.json —— 然后所有子包继承它

把严格规则放在最顶层;只有在确有需求时才下放例外。

// tsconfig.base.json at the repo root{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "lib": ["ES2022", "DOM"], "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "skipLibCheck": true, "declaration": true, "declarationMap": true, "verbatimModuleSyntax": true, "isolatedModules": true }}

子包配置:

{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", "rootDir": "src", "composite": true }, "include": ["src"]}

为什么能长期有效:统一的基础规则能够避免风格漂移和微妙的类型退化。


4)使用 TypeScript Project References + build mode

这决定了你的 monorepo 究竟是“任何改变都会触发全量构建”,还是“只构建变动部分”。

// packages/ui/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "composite": true, "outDir": "dist", "rootDir": "src" }, "references": [{ "path": "../auth" }]}

根目录脚本:

tsc -b packages/* # 以依赖图增量构建全部包tsc -b -w # watch 模式下使用 references

为什么能长期有效: 随着依赖图规模扩大,构建依然保持增量而不是变慢。


5)统一库构建工具:库用 tsup,开发用 tsx

不要同时操控多个 bundler。保持工具链简单直观。

// packages/auth/package.json{ "name": "@acme/auth", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "scripts": { "dev": "tsx watch src/index.ts", "build": "tsup src/index.ts --dts --format esm,cjs --clean" }}

为什么能长期有效:团队可能每年都会想换 bundler,但你不需要 —— tsup 和 tsx 足够快且可预期。


6)使用干净的 exports,不要允许 deep imports

只暴露你希望暴露的内容。应用层不应该通过packages/ui/src/button这种路径导入内部实现。

// packages/ui/package.json{ "name": "@acme/ui", "type": "module", "sideEffects": false, "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" } }, "files": ["dist"]}

为什么能长期有效:包内部的重命名不会影响整个 monorepo。


7)使用 Changesets 发布;两条命令自动化 release

人类可读的变更说明现在写好;自动化 semver 稍后执行。

// .changeset/config.json{ "changelog": "@changesets/cli/changelog", "commit": false, "linked": [], "access": "public", "baseBranch": "main"}// root package.json{ "scripts": { "changeset": "changeset", "version-packages": "changeset version", "release": "pnpm -r build && changeset publish" }}

为什么能长期有效:改动意图清晰,标记一致,不再有 “到底发布了啥?” 的疑问。


8)用 ESLint 强化边界,而不是靠团队默契

明确规定“谁可以 import 谁”。这样能减少争议。

// .eslintrc.cjs (root)module.exports = { root: true, parser: "@typescript-eslint/parser", plugins: ["@typescript-eslint", "import"], extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], rules: { "import/no-restricted-paths": ["error", { "zones": [ { "target": "./packages/auth", "from": "./packages/ui" }, // ui 不能 import auth { "target": "./packages/billing", "from": "./packages/auth"} // auth 不能 import billing ] }], "import/no-cycle": "error" }}

为什么能长期有效:边界设定存活在机器人和工具里,而不是口口相传的默契。


9)一个测试运行器,多项目共用:Vitest workspace

保持测试快速且一致。测试文件与代码邻近;从根目录一次性运行所有测试。

// vitest.workspace.ts at the rootimport { defineWorkspace } from 'vitest/config' export default defineWorkspace([ { test: { include: ['packages/auth/src/**/*.test.ts'] } }, { test: { include: ['packages/ui/src/**/*.test.tsx'] } }, { test: { include: ['apps/web/src/**/*.test.tsx'] } },])

为什么能长期有效:共用 reporters、快照与覆盖率,不需要为每个包定制配置。


10)集中管理环境变量类型:在 @acme/env 中用 Zod 校验

不要把process.env.FOO散落在代码各处。验证一次,到处复用。

// packages/env/src/index.tsimport { z } from "zod" const schema = z.object({ NODE_ENV: z.enum(["development", "test", "production"]), DATABASE_URL: z.string().url(), PORT: z.coerce.number().int().default(3000)}) export const env = schema.parse(process.env)export type Env = z.infer<typeof schema>

在任意应用中使用:

import { env } from "@acme/env"app.listen(env.PORT)

为什么能长期有效: 环境配置不正确会尽早失败 —— 还带着类型提示,而不是凌晨两点崩在生产上。


一些微小但长期有效的习惯

  • 库中优先使用 named exports,更易重构。

  • 每个包保留 README.md,记录其作用与示例 import。

  • 在 CODEOWNERS 中标注模块负责人,方便分流评审。

  • 添加 prepack 脚本,确保发布前构建正确。


结语

Monorepo 并不会因为某个“大问题”而失败,而是因为无数个小问题不断累积。以上十条约定能减少团队、包和需求增加所带来的摩擦。如果你也有经历战火、价值连城的经验技巧,欢迎分享 —— 我一定会借鉴(当然也会注明出处)。

地址:

https://medium.com/@kaushalsinh73/10-typescript-monorepo-conventions-that-age-well-c1a6841226f5

原文作者: Neurobyte

Node 社群

我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。 “分享、点赞、在看” 支持一波👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1173413.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2026年出国留学服务哪个更专业:五家优选全面对比 - 速递信息

——文章最新发布时间:2026年1月 一、推荐背景与评价体系 在全球留学申请竞争日益激烈且各国录取标准持续提升的背景下,选择一家专业可靠的出国留学机构已成为成功实现海外名校梦想的关键因素。全球留学不同于单一地区…

苹果终于眨眼了:打电话给谷歌救 Siri(对,真的是谷歌)

在苹果总部的某个角落&#xff0c;Siri 可能又一次礼貌地回了句&#xff1a;“我不太明白你的意思。”然后 Tim Cook 的脸——据说当场红到像煮熟的龙虾。接着&#xff0c;全世界最有钱的科技公司&#xff0c;干了一件很“反苹果”的事&#xff1a;给谷歌打电话求救。是的&…

分析各类原料分子包裹技术产品和服务厂家,全国排名如何? - 工业品牌热点

问题1:市场上各类原料分子包裹技术产品生产商那么多,怎么判断哪家价格合理? 对于有原料分子包裹技术需求的企业来说,价格合理从来不是单纯看报价数字,而是要结合成本结构交付质量和长期价值综合评估。很多企业容易…

Anthropic万字长文:一篇AI Agent评估体系的详细解析!

Datawhale干货 作者&#xff1a;Anthropic团队&#xff0c;来源&#xff1a;PaperAgentAnthropic发布了一篇blog《揭秘AI Agents评估》&#xff0c;细节满满&#xff01;原文略微有点长&#xff0c;整理了一张脑图&#xff0c;要点精髓&#xff1a;良好的评估&#xff08;evalu…

COSCon‘25 第十届中国开源年会登上中国日报,并获评思否「最受开发者欢迎的技术活动」

由开源社主办的 COSCon25 第十届中国开源年会于 2025 年 12 月在北京圆满落幕。开源驱动的下一代 AI 技术与生态、AI 时代的数据挑战、开源芯片的生态发展与未来趋势、新时代下的全球协作、被 AI 颠覆的 Coding、极速狂飙的具身智能开源浪潮…… 这些在开年 DeepSeek 时刻之后&…

2026年新加坡中学留学机构推荐:五家优选全面对比 - 速递信息

——文章最新发布时间:2026年1月 一、推荐背景与评价体系 在新加坡中学留学申请竞争日益激烈且录取标准持续提升的背景下,选择一家专业可靠的新加坡中学留学机构已成为成功实现新加坡优质教育梦想的关键因素。新加坡中…

2025年就业导向新西兰留学机构推荐:五家优选全面评测 - 速递信息

——文章最新发布时间:2026年1月 阅读摘要 文档类型:榜单评测与选型 评测维度:规划能力申请经验团队实力服务透明度增值服务Top Pick: 新东方前途出国 其它上榜: 新东方广州、启德教育、金吉列留学、新通教育 关键…

“买几送几“解题模板探讨

点击标题下「蓝色微信名」可快速关注现在小学生的数学题和我们小时候感觉不是一个层级的&#xff0c;例如"买几送几"应用题&#xff0c;还真得需要一些理解&#xff0c;可以通过如下的解题思路模板体会下&#xff0c;还是要对孩子多些宽容。第一步&#xff1a;找&quo…

MySQL自增id超过int最大值的场景

点击标题下「蓝色微信名」可快速关注 数据库的主键我们有时候会用自增列&#xff0c;但是自增都会有个上限&#xff0c;如果达到怎么办&#xff1f;技术社群的这篇文章《MySQL自增id超过int最大值怎么办&#xff1f;》就给我们讲解了MySQL数据库自增列达到上限该怎么办&#xf…

Instagram十亿级“用户名已被占用“背后的架构设计

点击标题下「蓝色微信名」可快速关注尽管国内无法访问但已经火遍全球的Ins软件&#xff0c;即Instagram&#xff0c;可能很多朋友都了解或者接触过&#xff0c;例如最近北京国安要引进的新外援&#xff0c;就是球迷们根据国安总经理马永明&#xff08;Matthias Brosamer&#x…

vue3怎么实现网页端的文件夹上传?

武汉码农の大文件上传奇遇记&#xff1a;在长江边写信创代码 各位好&#xff0c;我是小王&#xff0c;武汉光谷某软件公司"防脱发小组"组长。最近接了个政府项目&#xff0c;要求在信创环境下上传4G文件&#xff0c;还必须开源可审查——这就像让我用热干面调料写火…

百度WebUploader在vue-cli项目里怎么用文件夹上传?

作为一名前端开发工程师&#xff0c;我近期接手了公司一个有些年头的旧项目改造工作。这次改造的核心需求&#xff0c;是要给这个旧项目增添大文件上传功能&#xff0c;尤其得支持 10G 左右文件的上传&#xff0c;并且还要具备断点续传的能力。 在众多解决方案中&#xff0c;我…

html中如何用js实现大文件文件夹上传?

北京码农の10G文件上传奇遇&#xff1a;在胡同里写信创代码 各位好&#xff0c;我是老张&#xff0c;北京中关村某软件公司“脱发攻坚队”队长。最近接了个政府项目&#xff0c;要求上传10G文件&#xff0c;还必须兼容信创环境并提供全套文档——这活儿就像在故宫里装Wi-Fi&am…

【2026最新】电商数据分析平台实用解析:从选型到落地应用 - 速递信息

导语 随着电商运营日益精细,数据已成为店铺经营与决策的重要依据。数据显示,2025年超过七成电商从业者将数据分析视为日常运营的关键一环。面对市面上众多的数据工具,如何选择适配自身业务的分析平台成为商家普遍关…

教育平台如何用百度UE实现PPT内容无缝转存至网页?

CMS企业官网Word导入全攻略&#xff1a;一个.NET码农的求生之路 兄弟们好&#xff01;我是福建某小公司的.NET码农&#xff0c;最近接了个CMS企业官网的外包活&#xff0c;客户爸爸要求加个"Word全家桶一键导入"功能&#xff0c;还要保留所有妖艳的样式。预算680元封…

2026国际竞赛课程培训机构全景指南:从AMC备赛到升学竞争力提升 - 速递信息

在全球化升学竞争持续加剧的当下,国际竞赛已成为学生打造差异化学术背景、斩获世界名校offer的重要竞争力。其中,AMC数学竞赛作为国际认可度广泛的赛事之一,2026年仍保持高阶奖项含金量不变的核心优势,其成绩不仅是…

2026口碑柠檬茶加盟品牌梳理:从供应链到盈利模型拆解 - 速递信息

在规模达5000亿的茶饮市场中,柠檬茶凭借稳健的增长态势,成为众多创业者关注的细分赛道。但热潮背后,行业也存在不少现实挑战:对1900家门店的实地调研显示,仅30%的品牌能提供覆盖全周期的加盟支持,不少创业者因原…

深度测评9个论文写作工具,一键生成论文工具助研究生高效毕业!

深度测评9个论文写作工具&#xff0c;一键生成论文工具助研究生高效毕业&#xff01; AI 工具崛起&#xff0c;论文写作进入高效时代 在研究生阶段&#xff0c;论文写作往往是学生最头疼的任务之一。从选题、开题到撰写、修改&#xff0c;每一个环节都需要大量的时间和精力。而…

你不是在和AI竞争,你是在和“不用AI的自己”

导言&#xff1a;被误读的竞争关系 凌晨三点的告警邮件、重复的冒烟测试、永无止境的回归用例...当ChatGPT写出第一条测试脚本时&#xff0c;测试圈掀起海啸式恐慌。但真正需要警惕的并非AI&#xff0c;而是我们面对技术变革时固化的思维模式——软件测试的竞争本质&#xff0…

聚焦“十五五”人才战略,终成国际2026服务生态大会在青岛成功举办

1月16日&#xff0c;“智领新生 聚势前行——终成国际2026服务生态大会”在青岛西海岸新区成功举办。本次大会汇聚了相关政府领导、行业专家及企业领袖等300余位嘉宾&#xff0c;共同探讨在“十五五”即将开局的背景下&#xff0c;如何利用AI技术与全球化视野&#xff0c;重构…