在开发 npm 包时,主流的开发结构和模式有一定的共性,这些结构和模式主要是为了提高可维护性、扩展性以及代码质量。
以下是几种常见的 npm 包开发结构和模式:
一、package 结构
下面介绍常见的
package
结构及特性
1. 单一包结构 / 模式
这种单一包结构
/Monolith(单仓单包)模式
,适用于开发一个独立的 npm 包,代码和依赖相对简单。
目录结构:
my-package/
├── src/ // 源代码目录
│ ├── index.ts // 入口文件
│ ├── utils/ // 工具函数目录
├── tests/ // 测试代码
│ └── index.test.ts
├── dist/ // 编译后的输出目录(一般不会加入到源码管理)
├── package.json // npm 配置文件
├── tsconfig.json // TypeScript 配置文件
├── README.md // 包文档
├── .eslintrc.json // ESLint 配置
└── .prettierrc // Prettier 配置
关键特性:
- 适用于中小型 npm 包项目。
- 使用工具如
ESLint
、Prettier
来规范代码风格。 - 使用
Jest
或Vitest
等工具进行单元测试。 - 使用
TypeScript
来提供类型支持。 dist/
目录通常是通过构建工具(如Babel
或TypeScript
编译器)生成的发布代码。
构建工具:
Rollup
:常用的打包工具,适合小型库,支持生成UMD
、ESM
等多种格式。esbuild
:超快的 JavaScript 打包工具,适合追求编译速度的场景。Vite
:虽然更常用于开发应用,但也可以用于 npm 包的快速开发。
2. 多包结构 / 模式
这种多包结构
/Monorepo(单仓多包)模式
,适用于开发包含多个模块或工具的 npm 包项目,尤其是大型项目或库。
目录结构:
my-monorepo/
├── packages/
│ ├── package-a/
│ │ ├── src/
│ │ ├── package.json
│ ├── package-b/
│ │ ├── src/
│ │ ├── package.json
├── node_modules/
├── package.json // 根 package.json 文件
├── pnpm-workspace.yaml // pnpm workspace 配置
├── tsconfig.json // 根 tsconfig 文件
└── README.md
关键特性:
Monorepo
管理多个相互依赖的包,比如React
或Babel
都采用这种模式。pnpm
、Yarn Workspaces
或Lerna
通常用于管理依赖关系和工作空间。- 每个包(
package-a
、package-b
)可以有自己独立的package.json
文件,但通过统一的工具管理。 - 通常支持共享工具链,如
ESLint
、Prettier
、Jest
等。
构建工具:
Lerna
:经典的Monorepo
管理工具,用于管理版本、依赖、发布等。Turborepo
:新兴的高性能Monorepo
管理工具,支持并行任务执行。pnpm
或Yarn workspaces
:用于管理工作空间的依赖和共享依赖
二、特性包(库)的开发特点
以下介绍几个常见的特性依赖包的开发特点
1. UI 组件
开发 UI 组件库,侧重样式管理和文档演示。
目录结构:
my-ui-library/
├── src/
│ ├── components/ // 组件目录
│ ├── index.ts // 入口文件
├── themes/ // 主题和样式文件
│ ├── default.scss // 默认主题样式
├── stories/ // Storybook 文件
│ └── Button.stories.tsx
├── dist/ // 打包输出目录
├── package.json
├── tsconfig.json
├── README.md
├── .storybook/ // Storybook 配置
└── .eslintrc.json // ESLint 配置
关键特性:
- 使用
Sass
、Less
或CSS-in-JS
来管理样式。 - 使用
Storybook
或VitePress
生成组件文档及可视化展示。 - 使用
Rollup
或Vite
进行打包,通常会输出多种格式(ESM
、CJS
)。 - 组件通常是
按需加载
的,因此需要支持树摇
优化(tree-shaking
)。
2. 函数
开发此类包/库,主要提供的是工具函数或 API,可以采用较为简洁的目录结构。
目录结构:
my-utility-library/
├── src/
│ ├── index.ts // 函数库的主入口
│ ├── utils/ // 各种工具函数
├── tests/
│ ├── index.test.ts // 单元测试
├── dist/ // 打包输出目录
├── package.json
├── tsconfig.json
├── README.md
├── .eslintrc.json // ESLint 配置
└── .prettierrc // Prettier 配置
关键特性:
- 核心是
函数
或类
的实现,通常强调小而美的设计。 - 强调
类型安全性
,通常会有TypeScript
的完整支持。 单元测试
非常重要,确保函数逻辑的准确性
。
3. 插件
这种模式适用于开发针对其他框架或系统的插件(如 Babel
插件、Webpack
插件)。
目录结构:
my-plugin/
├── src/
│ ├── index.ts // 插件的核心代码
├── tests/
│ ├── plugin.test.ts
├── dist/
├── package.json
├── tsconfig.json
└── README.md
关键特性:
- 针对
特定
框架或工具提供扩展
功能。 - 插件类库通常包含对目标工具的钩子或配置函数。
- 需要有较好的文档支持,帮助用户理解如何集成和使用。
三、常见工具链
TypeScript
:用于类型安全的开发。Rollup / Vite / Parcel / esbuild
:打包工具,根据项目大小选择合适的工具。Jest / Vitest
:用于编写单元测试。ESLint / Prettier
:用于代码质量和风格的检查。pnpm / Lerna
:用于依赖管理和 Monorepo 管理。
四、总结
- 选择合适的结构和模式,取决于 npm 包的规模、功能以及未来的扩展性需求。
- 对于中小型库,单包结构即可满足;
- 而对于大型项目或多个包组成的项目,Monorepo 模式更为合适。
- 根据具体情况选择相应的工具和开发模式,是提高开发效率和代码质量的关键。