ESModule通过标准化接口契约、目录结构、构建产物和协作治理实现组件复用。统一命名导出、index聚合、职责分明的子目录、多格式产物(ESM/CJS/.d.ts)、SemVer版本控制、自动化CHANGELOG与CI导出校验共同构成可信赖的组件交付体系。

ESModule本身不直接“输出组件”,而是提供一套标准化的模块封装与消费机制。在多团队协同场景中,要让业务组件真正具备标准、通用、可复用的属性,关键在于把ESModule作为载体,配合明确的接口契约、一致的构建规范和清晰的发布策略。
统一导出接口:定义最小、稳定、语义化的API
每个业务组件应通过命名导出(Named Export)暴露明确的功能单元,避免默认导出模糊主次。例如:
-
导出组件本身:
export const UserCard = () => {...} -
导出配套Hook:
export const useUserActions = () => {...} -
导出类型定义(TypeScript):
export interface UserCardProps { ... } -
导出常量或配置项:
export const USER_CARD_SIZES = ['sm', 'md', 'lg'] as const;
不导出内部工具函数、副作用逻辑或未文档化的私有状态——所有导出必须出现在index.ts或index.js中,并经过跨团队评审确认。
结构即契约:采用标准化目录与入口组织
组件包根目录下强制包含index.ts(或index.js),且只做聚合导出,不写业务逻辑:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
// packages/user-card/index.ts
export { UserCard } from './components/UserCard';
export { useUserActions } from './hooks/useUserActions';
export type { UserCardProps } from './types';
export { USER_CARD_SIZES } from './constants';
子目录按职责划分(components/、hooks/、types/、constants/),禁止嵌套超过2级。这种结构让任意团队都能快速理解“这个包能提供什么”,无需翻查源码路径。
构建与交付:生成多格式产物,适配不同消费环境
单个ESModule源码需通过构建工具(如Rollup或Vite)输出三类标准产物:
- ESM格式(.mjs):供现代打包器(Vite/Webpack 5+)原生消费,支持Tree Shaking
- CommonJS格式(.cjs):兼容Node.js脚本、旧版工具链及服务端渲染(SSR)场景
- 类型声明文件(.d.ts):完整导出类型,确保TypeScript项目零配置接入
package.json中明确标注字段:
"type": "module",
"exports": {
".": {
"import": "./dist/user-card.mjs",
"require": "./dist/user-card.cjs",
"types": "./dist/user-card.d.ts"
}
},
"types": "./dist/user-card.d.ts"
协作治理:版本、文档与演进约束
多团队共用组件不是“扔出去就完事”,需要轻量但有效的治理机制:
- 语义化版本(SemVer)强制执行:任何导出API的删除、重命名、参数变更都必须升主版本(v2.0.0)
- 变更日志(CHANGELOG.md)自动化生成:基于Conventional Commits,让各团队一眼识别影响范围
- 在线文档页集成示例:每个组件附带可运行的CodeSandbox链接,含基础用法、定制场景、无障碍说明
-
CI阶段校验导出稳定性:使用
api-extractor扫描每次PR,阻断意外导出或类型破坏
这样,一个@org/user-card包对消费方而言就是“开箱即用的标准零件”:导入方式统一、类型安全、行为可预期、升级风险可控。

















