setup-ts-deep-modules

将 dependency-cruiser 接入 TypeScript 仓库,使每个 package 成为深层模块,实现代码隐藏在子文件夹中,只能通过其入口文件访问。由用户主动调用。

提供方:mattpocock/skills调用次数:7.2k收藏:325更新:2026/08/28

技能说明mattpocock/skills

将 dependency-cruiser 接入 TypeScript 仓库,使每个 package 成为深层模块,实现代码隐藏在子文件夹中,只能通过其入口文件访问。由用户主动调用。

技能简介

本技能将 dependency-cruiser 接入 TypeScript 仓库,强制每个 package 成为“深层模块”:实现代码隐藏在各 package 的子文件夹中,外部代码只能通过该 package 的入口文件(根目录文件)访问。它帮你治理大型 TS 仓库的跨包依赖边界,防止深层导入和循环依赖。

使用场景

  • 多包 TypeScript 仓库中,规范各个 package 之间的依赖边界
  • 防止业务代码或测试代码绕过入口文件、直接深入导入其他包的内部实现
  • 让每个 package 形成“小接口、大实现”的结构,便于重构与长期维护
  • 落实“测试只通过入口文件访问”的架构约定,保证集成测试合法、深层导入不可能
  • 作为团队规范落地工具,让架构约束通过 CLI 自动检查,而不是靠 code review

使用方法

本技能由用户主动调用,执行步骤如下(以 pnpm 为例,实际可替换为 yarn/npm/bunx):

  1. 检测环境:确认包管理器(pnpm-lock.yaml → pnpm,yarn.lock → yarn,bun.lockb → bun,否则 npm)。确认 packages 根目录(存在 src/ 则用 src/packages,否则用 packages)。若已有 .dependency-cruiser.* 配置,不要覆盖,需合并。

  2. 安装依赖:将 dependency-cruiser 安装为 devDependency。

    pnpm add -D dependency-cruiser
    
  3. 写入配置:将 dependency-cruiser.config.cjs 复制为仓库根目录下的 .dependency-cruiser.cjs,并设置 PACKAGES_ROOT 为检测到的根目录。规则基于路径深度,无需其他适配。

  4. 接入检查流程:添加 lint:boundaries 脚本:

    depcruise src   # 或 depcruise packages
    

    lint:boundaries 并入仓库现有的总检查命令(与 typecheck 在同一命令中运行)。不要修改 tsconfig,不要添加路径别名。

  5. 搭建示例包:在 <packages-root>/example/ 创建可复制模板,包含入口 index.ts、子目录实现 lib/impl.ts、测试 tests/example.test.ts(只从 ../index 导入)。

  6. 验证规则生效:先运行 lint:boundaries,应通过;在测试里临时添加深层导入(如 import { thing } from "../lib/impl"),再运行应 失败;撤销该导入后应再次通过。

  7. 记录约定:在 packages 根目录写 README.md,说明目录布局和“只能通过入口文件导入”的约定。

注意事项

  • 入口文件 ≠ 单一 index.ts。每个根目录文件都是入口,包可以暴露多个小入口(如 index.tsclient.tsserver.ts);不要用 barrel 文件把整个子树重新导出。
  • 已有 dependency-cruiser 配置时 不要覆盖,而是合并规则并告知用户新增内容。
  • 包与包之间的分层依赖(如 core 与 feature 的上下层关系)是独立关注点,配置中留有注释占位,由仓库自行补充。
  • 技能完成标准是“规则咬得住”:必须观察到对深层导入的导入会失败,否则视为未正确接线,需修复后再结束。
  • 无 umbrella check 脚本时,lint:boundaries 需由用户手动加入 CI。