关于 npm-package
面向单包 npm 库开发与发布的技能,以 Bun 为主要工具链,涵盖项目配置、兼容性、测试和发布流程。
主要功能
- 01生成 npm 包项目骨架
- 02配置 ESM 或 CJS/ESM 双格式输出
- 03设置 TypeScript 声明与导出
- 04配置 Biome、ESLint 和 Vitest
- 05准备 npm 发布流程
适用场景
- 01从头创建 npm 库
- 02修复模块互操作或类型声明问题
- 03配置包检查与测试
- 04发布前检查包配置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jwynia/ agent-skills --skill npm-package安装后在 Claude Code 中输入/npm-package确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
reference/esm-cjs-guide.mdpublishing-workflow.mdstrict-typescript.mdscripts/scaffold.tstemplates/biome.jsonbunup.config.tseslint.config.tsgitignorepackage.json.hbstsconfig.jsonvitest.config.tstemplates/src/index.test.ts.hbsindex.ts.hbs详细介绍
npm 包开发(Bun 优先)
使用 Bun 作为主要运行时和工具链来构建并发布 npm 包,确保产物能在 npm 包的所有使用场景中正常工作。
何时使用此技能
适用于:
- 从头创建新的 npm 库包
- 为现有包配置构建、测试和 lint 工具
- 修复 CJS/ESM 互操作、导出映射或 TypeScript 声明问题
- 将包发布到 npm
- 审查或改进包配置
不适用于:
- 构建可通过 npx 执行的 CLI 工具(使用
npx-cli技能) - 构建应用程序(而非已发布的包)
- 在 monorepo 中工作(此技能面向单包仓库)
工具链
| 事项 | 工具 | 原因 |
|---|---|---|
| 运行时 / 包管理器 | Bun | 安装、运行和转译速度快 |
| 打包工具 | Bunup | 原生支持 Bun、双格式输出、生成 .d.ts |
| 类型声明 | Bunup(通过 tsc) | 集成在构建流程中 |
| TypeScript | module: "nodenext"、strict: true + 额外选项 | 确保已发布代码的正确性 |
| 格式化 + 基础 lint | Biome v2 | 比 ESLint 快 10-25 倍,使用单一工具 |
| 类型感知 lint | ESLint + typescript-eslint | 提供 40 多条 Biome 无法实现的类型感知规则 |
| 测试 | Vitest | 测试隔离、成熟的模拟功能和覆盖率 |
| 版本管理 | Changesets | 基于文件、明确、适用于 monorepo |
| 发布 | npm publish --provenance | 可信发布 / OIDC |
搭建新包的脚手架
运行脚手架脚本,生成完整项目:
bun run <skill-path>/scripts/scaffold.ts ./my-package \
--name my-package \
--description "What this package does" \
--author "Your Name" \
--license MIT
选项:
--dual— 生成双 CJS/ESM 输出(默认:仅 ESM)--no-eslint— 跳过 ESLint,仅使用 Biome
然后安装依赖:
cd my-package
bun install
bun add -d bunup typescript vitest @vitest/coverage-v8 @biomejs/biome @changesets/cli
bun add -d eslint typescript-eslint # unless --no-eslint
项目结构
my-package/
├── src/
│ ├── index.ts # Package entry point — all public API exports here
│ └── index.test.ts # Tests co-located with source
├── dist/ # Built output (gitignored, included in published tarball)
├── .changeset/
│ └── config.json
├── package.json
├── tsconfig.json
├── bunup.config.ts
├── biome.json
├── eslint.config.ts # Type-aware rules only
├── vitest.config.ts
├── .gitignore
├── README.md
└── LICENSE
关键配置细节
修改任何配置前,请阅读以下参考文档。这些文档解释了各项决策背后的原因,以及可能导致隐蔽故障的注意事项:
- reference/esm-cjs-guide.md —
exports映射配置、双包隐患、module-sync、常见错误 - reference/strict-typescript.md — tsconfig 原理、Biome 规则、ESLint 类型感知规则、Vitest 配置
- reference/publishing-workflow.md — Changesets、
files字段、可信发布、CI 流水线
关键规则(不可妥协)
违反以下规则会导致已发布包中最常见、影响最严重的问题。请务必遵守,不得例外。
包配置
-
始终在 package.json 中使用
"type": "module"。 仅 ESM 是正确的默认选择。所有受支持的 Node.js 版本都支持require(esm)。 -
始终使用
exports字段,不要使用main。main已过时。exports可精确控制使用者能够访问的内容。 -
每个 exports 块中,
types必须是第一个条件。 否则 TypeScript 会静默地无法解析类型。 -
始终导出
"./package.json": "./package.json"。 许多工具需要访问 package.json,而exports会完全封装包的内容。 -
在 package.json 中使用
files: ["dist"]。 白名单方式可防止意外发布机密信息。切勿使用.npmignore。 -
每次发布前都运行
npm pack --dry-run。 确认压缩包恰好包含你想要发布的内容。
TypeScript
-
已发布的包应使用
module: "nodenext"。 不要使用"bundler"。符合 nodenext 要求的代码可在任何地方运行,反之则不然。 -
strict: true不可妥协。 否则,你的 .d.ts 文件可能包含会导致使用 strict 模式的使用者报错的类型。 -
启用
noUncheckedIndexedAccess。 捕获因未检查的数组或对象访问导致的真实运行时错误。 -
发布
declarationMap: true。 让使用者能够通过“转到定义”定位到原始源代码。 -
已发布的包中不要使用路径别名(
paths)。 tsc 不会在生成的代码中重写它们,使用者将无法解析这些别名。
代码质量
-
禁止使用
any。 使用unknown并进行收窄。只有在确实无法避免时,才使用// biome-ignore suspicious/noExplicitAny: <reason>抑制检查,并始终说明原因。 -
优先使用命名导出,而非默认导出。 默认导出在 CJS/ESM 边界上的行为有所不同。
-
类型专用导入一律使用
import type。verbatimModuleSyntax和 Biome 的useImportType规则都会强制执行此项要求。
构建
-
使用 Bunup 构建,并设置
format: ['esm'](双格式构建则设置为['esm', 'cjs'])。Bunup 会处理 .d.ts 生成、外部依赖检测以及正确的文件扩展名。 -
在 package.json 中将
engines.node设为>=20.19.0。这会注明最低支持的 Node.js 版本(首个支持稳定require(esm)的 LTS 版本)。
测试
-
使用 Vitest,而非 bun:test。 bun:test 缺乏测试隔离机制,模块模拟会在文件之间泄漏。Vitest 会在各自的工作线程中运行每个测试文件。
-
设置覆盖率阈值(分支、函数、行和语句覆盖率均 ≥ 80%)。在 vitest.config.ts 中强制执行。
开发工作流
# Write code and tests
bun run test:watch # Vitest watch mode
# Check everything
bun run lint # Biome + ESLint
bun run typecheck # tsc --noEmit
bun run test # Vitest run
# Build
bun run build # Bunup → dist/
# Prepare release
bunx changeset # Create changeset describing changes
bunx changeset version # Bump version, update CHANGELOG
# Publish
bun run release # Build + npm publish --provenance
添加子路径导出
当包需要公开多个入口点时:
- 添加源文件:
src/utils.ts - 将其添加到 bunup.config.ts 的 entry 中:
entry: ['src/index.ts', 'src/utils.ts'] - 将其添加到 package.json 的 exports 中:
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./utils": {
"types": "./dist/utils.d.ts",
"default": "./dist/utils.js"
},
"./package.json": "./package.json"
}
}
提醒: 添加或移除导出路径属于 semver 主版本变更。
切换到 CJS/ESM 双格式输出
如果消费者需要支持 Node.js < 20.19.0 的 CJS:
- 更新 bunup.config.ts:
format: ['esm', 'cjs'] - 更新 package.json 的 exports,加入
module-sync、import和require条件 - 有关 exports 映射的确切结构,请参阅 reference/esm-cjs-guide.md
Bun 特有注意事项
bun build不会生成 .d.ts 文件。 使用 Bunup(它会委托给 tsc),或单独运行tsc --emitDeclarationOnly。bun build的 CJS 输出仍处于实验阶段。 对于可发布到 npm 的 CJS,始终使用target: "node"。target: "bun"会生成 Bun 专用包装器。bun build不会降级语法。 现代 ES2022+ 语法会原样发布。若要面向较旧的运行时,还需进行额外转译。bun publish不支持--provenance。 如需进行来源证明签名,请使用npm publish。bun publish使用NPM_CONFIG_TOKEN,而非NODE_AUTH_TOKEN。可能需要调整 CI 流水线。