还在写 index.ts 垃圾桶?是时候删掉它了!

0 阅读4分钟

在很多 TypeScript 项目中,index.ts 几乎成为了一种默认的导出方式。你可以在每个模块或文件夹中看到它的身影,负责将当前目录下的所有函数、组件、常量统一导出,然后在其他模块中以更简洁的路径进行引用。

这种做法初看起来非常“优雅”——简化了路径,减少了导入时的工作量。尤其是在多个导出文件需要被聚合使用时,似乎使用 index.ts 是唯一的选择。

但我们项目的重构实践告诉我们:index.ts 是一个“隐形炸弹”,会破坏 RSC/CSC 结构、污染 import 路径、拉高构建成本、影响 Tree Shaking 效果,甚至对 Next.js 的页面打包体积产生严重影响。


index.ts 的四大隐性危害

1. 聚合导出污染依赖图谱

一个 index.ts 文件如果统一导出了多个子模块,那在引用它的地方,哪怕只使用其中某一个成员,也可能间接引入所有导出的内容,从而扩大构建体积,破坏原子性。

这会导致:

  • 组件树中的 RSC/CSC 隔离失效
  • 无法进行 静态分析与代码分割
  • 项目整体 import 图谱模糊化

2. 导致 Tree Shaking 失败

在一些构建工具(包括 Webpack 和旧版本的 Next.js 构建系统)中,index.ts 的聚合导出极易造成 Tree Shaking 失败,即使没有实际使用某个模块,也可能被打包进最终构建产物中。

3. 形成循环依赖黑洞

如果两个模块都通过 index.ts 导入对方,很容易在大型项目中无意中构建出循环依赖。这种依赖在早期很难察觉,但一旦触发,就会造成构建失败或运行时异常。

4. 阻碍组件追踪和调试

使用 index.ts 后,组件名、文件路径与真实定义位置之间建立起了额外的一层间接跳转,导致你在追踪组件来源时需要多跳一层,调试和重构都变得更困难。


✅ 项目重构:我们是如何禁用 index.ts 的?

我们制定了明确的导入与组件管理规范,逐步替代掉所有 index.ts 的用法:

✅ 简单组件采用扁平结构

  • 文件名即为组件名,如 aspect-ratio-card.tsx
  • 对外暴露时使用绝对路径,避免文件夹包裹,结构扁平
import AspectRatioCard from '@/shared/components/aspect-ratio-card';

✅ 复杂组件使用 index.tsx

如果一个组件拥有多个子组件、hook 或内部逻辑较复杂,则使用文件夹方式管理,主组件写在 index.tsx,仅负责导出自己,避免变成“垃圾桶”。

/components
  └─ fancy-widget/
      ├─ index.tsx  # ✅ 只导出自己
      ├─ useFeature.ts
      └─ internal-part.tsx

✅ 类型单独导出

我们强制使用 import type 明确区分类型导入与值导入,避免混淆组件与类型之间的边界。

import type { FancyWidgetProps } from '@/types/fancy-widget';

📊 实证:真实 next build 数据对比

我们保留了项目在删除 index.ts 前后的 next build 数据:

🔺 删除前

  • 页面平均 FLJ:264KB 左右
  • 部分页面首次加载 JS 超过 300KB

🔻 删除后

  • 页面平均 FLJ:237KB 左右
  • 全站首次加载体积下降 10% - 15%
  • 无需任何业务逻辑改动,仅删除了 index.ts

deleted_index.png

✅ 我们并没有开启新的组件拆分、也没有新增 lazydynamic,单纯地删除 index.ts,就取得了立竿见影的效果!


🚀 是时候做出改变了

如果你曾在项目中无数次困惑于“到底这个组件从哪儿来的”,如果你曾在重构中不小心删掉一个 index.ts 导致半个项目崩溃——现在,就是你对 index.ts 说再见的最佳时机。

我们不是为了追求完美,而是为了获得清晰、可控、可维护的代码结构。移除 index.ts,不是“回到原始”,而是用显式路径去换取显性逻辑,让每一次导入都可追踪,每一份构建都更轻量。

✅ 从今天起,试着:

  • 拆除一个 index.ts
  • 改写一次绝对路径导入
  • 分离一次 RSC 与 CSC 的职责

别等下一次构建体积爆炸,才想起结构隐患的根源。现在开始,让项目结构为你服务,而不是成为你的负担。


作者: AiMuo / Toolbox Project

Follow the journey of building a modular, RSC-first toolbox at aimuo.com