4.0 KiB
4.0 KiB
name, description
| name | description |
|---|---|
| library-development | 使用 tsdown 构建和发布 TypeScript 库。适用于创建 npm 包、配置库打包或设置 package.json 导出字段时。 |
库开发
| 方面 | 选择 |
|---|---|
| 打包工具 | tsdown |
| 输出格式 | 仅纯 ESM(无 CJS) |
| 类型声明 | 通过 tsdown 生成 |
| 导出 | 通过 tsdown 自动生成 |
tsdown 配置
使用 tsdown 并启用以下选项:
// tsdown.config.ts
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
exports: true,
})
| 选项 | 值 | 用途 |
|---|---|---|
format |
['esm'] |
纯 ESM,无 CommonJS |
dts |
true |
生成 .d.ts 文件 |
exports |
true |
自动更新 package.json 中的 exports 字段 |
多个入口点
export default defineConfig({
entry: [
'src/index.ts',
'src/utils.ts',
],
format: ['esm'],
dts: true,
exports: true,
})
当运行 tsdown 时,exports: true 选项会自动生成 package.json 中的 exports 字段。
API 稳定性
对于已发布的库,锁定公开 API 表面,使意外的破坏性变更在代码审查中以差异形式显现。
| 工具 | 用途 |
|---|---|
tsnapi |
通过 Vitest 将运行时导出与类型声明快照到已提交的 .snapshot.js / .snapshot.d.ts 文件中 |
tsdown-stale-guard |
记录构建输入/输出哈希值,以便针对过时构建运行测试时快速失败 |
将两者安装为开发依赖。将 tsdown-stale-guard 作为 tsdown 插件接入,使每次构建都记录其哈希值:
// tsdown.config.ts
import { defineConfig } from 'tsdown'
import { StaleGuardRecorder } from 'tsdown-stale-guard'
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
exports: true,
plugins: [
StaleGuardRecorder(),
],
})
从 Vitest 测试中快照公开 API——优先使用 Vitest 辅助函数而非 tsdown/Rolldown 插件,以便构建配置专注于构建。每个文件通过一个文件级别的 beforeAll(guardStaleBuild) 来确保构建是最新的,从而使已提交的 dist/ 永远不会与源码脱节:
// test/api.test.ts(单个包)
import { beforeAll } from 'vitest'
import { snapshotApiPerEntry } from 'tsnapi/vitest'
import { guardStaleBuild } from 'tsdown-stale-guard'
beforeAll(async () => {
await guardStaleBuild()
})
await snapshotApiPerEntry(new URL('..', import.meta.url).pathname)
对于 monorepo,将 describePackagesApiSnapshots() 包裹在 describe 中,使每个包的测试套件共享一个过时构建检测门:
// test/api.test.ts(monorepo,从根目录运行)
import { beforeAll, describe } from 'vitest'
import { describePackagesApiSnapshots } from 'tsnapi/vitest'
import { guardStaleBuild } from 'tsdown-stale-guard'
describe('packages api', async () => {
beforeAll(async () => {
await guardStaleBuild()
})
await describePackagesApiSnapshots()
})
更新快照
在有意的 API 变更之后,一次性重建并更新两个快照:
nr build # 重新生成 dist/ 和过时构建哈希值
nr test -u # 更新 .snapshot.js / .snapshot.d.ts 文件
package.json
纯 ESM 库的必填字段:
{
"type": "module",
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": ["dist"],
"scripts": {
"build": "tsdown",
"prepack": "pnpm build",
"test": "vitest",
"release": "bumpp -r"
}
}
当 exports: true 时,exports 字段由 tsdown 管理。
prepack 脚本
对于每个公开包,在 scripts 中添加 "prepack": "pnpm build"。这确保在发布前(例如运行 npm publish 或 pnpm publish 时)自动构建该包。这可以防止意外发布过时或缺失的构建产物。