ES Modules导出应统一、可预测、易维护:命名导出用于多个平等成员,默认导出仅限主实体;保持扁平结构、避免嵌套;入口index.js仅re-export且显式声明;强制JSDoc+TS校验类型与文档。

团队采用 ES Modules 时,导出标准的核心是统一、可预测、易维护。重点不是“能导出”,而是让每个模块的接口意图清晰、导入方式一致、重构成本低。
明确区分命名导出和默认导出的语义
命名导出用于暴露多个、平等、可组合的成员(如工具函数、常量、类型);默认导出只用于该模块的“主实体”——通常是类、核心对象或工厂函数。一个模块不应同时有多个默认导出,也不应把所有东西都塞进默认导出里。
- ✅ 推荐:一个工具模块导出多个函数:
export const debounce = ...、export const throttle = ... - ✅ 推荐:一个组件模块默认导出 React 组件:
export default function Button() { ... } - ❌ 避免:把整个配置对象设为默认导出,而把其中的 key(如
apiUrl、timeout)又单独命名导出,造成重复和歧义
导出结构保持扁平,避免深层嵌套引用
不鼓励在模块中导出一个大对象再从中解构使用,比如 export const utils = { debounce, throttle }。这会让调用方必须写 utils.debounce,失去 tree-shaking 优势,也增加阅读负担。
- ✅ 正确做法:直接命名导出每个函数:
export { debounce, throttle };或逐行export const debounce = ... - ✅ 若需聚合,可在入口层(如
index.js)统一 re-export:export { debounce, throttle } from './utils/debounce.js'; - ⚠️ 注意:聚合导出时不要改变原始名称,避免别名混乱(除非有强理由,如跨版本兼容)
统一模块入口与命名约定
团队应约定每个功能域的主模块路径和导出方式。例如:
立即学习“Java免费学习笔记(深入)”;
- 所有业务 API 模块以
api/xxx.js存放,默认导出一个封装了 axios 实例的 service 对象,命名导出对应接口函数:export const getUser = ...、export const updateUser = ... - 所有工具模块以
utils/xxx.js存放,只用命名导出,禁止默认导出 - 每个目录下设
index.js作为聚合入口,仅做 re-export,不写逻辑;且该文件必须显式列出所有导出项,不使用export * from(防止隐式泄漏)
强制类型与文档前置(尤其对公共模块)
ESM 本身不校验类型,但团队可通过 JSDoc + TypeScript 编译检查来保障导出接口的稳定性:
- 每个命名导出的函数/类必须带
@param、@returns、@example - 默认导出需注明用途,如
/** @module Button - 主按钮组件 */ export default function Button() { ... } - CI 流程中加入
tsc --noEmit校验导出签名是否匹配声明,避免“导出了却没定义类型”的情况


















