@composy/builder
@composy/builder
@composy/builder
是一个面向 TypeScript 库、组件库、工具库与 CLI 包的构建工具。它提供零配置分析、可扩展配置系统、多打包引擎适配、构建后样式补链、package.json
自动回写和产物自检能力,适合在 monorepo 中统一维护发布链。
核心能力
- 零配置分析:自动识别项目入口、框架类型、推荐 external、UMD globals 与输出布局。
- 多引擎适配:默认使用
rolldown,并内置rollup、esbuild、swc、vite、rspack、turbopack适配器。 - 多框架策略:支持
TypeScript、React、Vue 2/3、Svelte、Solid、Preact、Lit、Angular、Qwik、Astro、Remix、Nuxt 3与混合框架场景。 - 样式产物整理:构建后可为
es/lib写入编译 CSS,为esm保留样式源码,并为dist聚合样式文件。 - 包元数据维护:根据真实输出目录更新
exports、files、样式导出与主入口字段。 - 产物自检:对入口文件、声明文件、UMD 文件与聚合样式做轻量校验,提前暴露发布面漂移。
- 项目诊断:通过
ldesign-builder doctor检查配置、入口、package.json发布面和可选产物布局。 - CLI 与编程式 API 并存:既可直接使用
ldesign-builder,也可通过LibraryBuilder、ConfigManager等 API 集成到自定义脚本中。
安装
pnpm add -D @composy/builder
快速开始
1. 零配置构建
当项目结构符合常见库目录约定时,可以直接运行:
pnpm exec ldesign-builder build
在交互式终端中,build
会先询问本次是否升级包版本。选择升级后,可用上下键从 Patch、Minor、Major、Alpha、Beta、RC 和自定义精确版本中选择;每个选项都会显示
当前版本 → 目标版本
与适用场景。目标包版本会在构建前写入,只有完整构建成功后,builder 才会在检测到的 pnpm/npm/yarn/bun
workspace 中同步所有消费方的
dependencies、devDependencies、peerDependencies、optionalDependencies 和 pnpm
catalog 引用,并刷新 lockfile。构建或同步失败时会回滚本次版本事务。
CI、管道和其他非 TTY 环境不会等待输入,默认保持版本不变;请显式指定方案:
# 自动化发布构建
pnpm exec ldesign-builder build --version-bump minor
# 指定精确版本
pnpm exec ldesign-builder build --version-bump 2.0.0-rc.0
# 明确跳过询问;也可使用 --version-bump none
pnpm exec ldesign-builder build --no-version-prompt
# 特殊流程中保留消费方声明或 lockfile
pnpm exec ldesign-builder build --version-bump patch --no-workspace-update
pnpm exec ldesign-builder build --version-bump patch --no-lockfile-update
build --watch
不会开启一次性版本事务;如需升级,请先完成一次普通 build,再启动 watch。build --dry-run --version-bump minor
只展示版本计划,不写文件。
如果你想先确认最终解析到的配置和构建计划,而不真正写出产物,可以使用:
pnpm exec ldesign-builder build --print-config --dry-run
如果要复用预设,可在配置文件之后、CLI 显式覆盖之前应用构建预设:
pnpm exec ldesign-builder build --profile ci --dry-run
builder 会优先尝试自动分析:
src/index.ts等常见源码入口package.json中的包名、依赖、peerDependencies- 当前项目的框架特征与输出需求
版本规划、workspace 检测与依赖同步
build 的版本事务分成“规划、构建、提交”三个阶段:
- 规划阶段在初始化 builder 前读取当前包的
package.json,确认当前版本并计算目标版本。 - 构建阶段先把目标版本写入当前包,使构建产物和包元数据使用同一个版本;随后执行普通构建、DTS、报告、体积限制和资源清理。
- 提交阶段只在上述步骤全部成功后更新 workspace 消费方、catalog 和 lockfile。任何阶段失败都会恢复当前包版本;workspace 同步失败还会恢复已修改的 manifest、
pnpm-workspace.yaml和 lockfile 快照。
只要本次事务确实升级了版本,提交阶段还会在当前包目录生成或更新
CHANGELOG.md。日志会记录构建工具、版本前后值、workspace 消费方的每个依赖字段变更、catalog/lockfile 状态,并结合 Git 提交按类型、作者、提交哈希、Breaking
Changes 和统计信息生成详细条目。Git 历史不可用时会降级写入完整的版本事务摘要;日志及其降级摘要都无法写入时会和版本事务一起回滚。未升级版本、--dry-run
和 --watch 不会生成日志。
交互式版本选择
在真实 TTY 中,执行 ldesign-builder build
会先询问是否升级版本。选择“升级”后,使用上/下方向键移动,按 Enter 确认。菜单会同时展示当前版本、目标版本和使用场景:
| 方案 | 版本规则 | 适用场景 |
|---|---|---|
| Patch | x.y.Z |
向后兼容的问题修复 |
| Minor | x.Y.0 |
向后兼容的新功能 |
| Major | X.0.0 |
包含破坏性变更 |
| Alpha | x.y.z-alpha.N |
早期预览,API 仍可能变化 |
| Beta | x.y.z-beta.N |
功能基本完整,继续收集兼容性反馈 |
| RC | x.y.z-rc.N |
发布候选版本,只接受发布阻断修复 |
| 自定义 | 任意高于当前版本的合法 SemVer | 需要精确指定版本或预发布标识 |
Alpha、Beta 和 RC 会根据当前版本自动计算下一序号;自定义版本必须是合法 SemVer,且严格高于当前版本。选择“不升级”时只执行构建,不修改版本或 workspace 依赖。
CI、脚本和非 TTY 环境
非 TTY、CI 或 TERM=dumb 环境不会等待键盘输入,默认保持当前版本。自动化流程应显式提供版本方案:
# 语义化升级
pnpm exec ldesign-builder build --version-bump patch
pnpm exec ldesign-builder build --version-bump minor
pnpm exec ldesign-builder build --version-bump major
pnpm exec ldesign-builder build --version-bump alpha
pnpm exec ldesign-builder build --version-bump beta
pnpm exec ldesign-builder build --version-bump rc
# 精确版本(包括预发布版本)
pnpm exec ldesign-builder build --version-bump 2.0.0-rc.0
# 明确不升级版本
pnpm exec ldesign-builder build --version-bump none
pnpm exec ldesign-builder build --no-version-prompt
--version-bump 也可以通过环境变量 LDESIGN_BUILDER_VERSION_BUMP
提供,适合统一的发布脚本。命令行参数优先于环境变量。
workspace 检测规则
builder 会从当前包目录向上查找 workspace 根目录,支持:
pnpm-workspace.yaml的packages配置;- 根
package.json的workspaces数组或{ "packages": [...] }配置; - pnpm、npm、Yarn 和 Bun 的常见 lockfile。
包管理器的判断优先使用 workspace 根 package.json 中的 packageManager 声明,例如
"packageManager": "pnpm@10.0.0";没有明确声明时,才根据现有 lockfile 推断。这样可以避免目录中同时存在多个 lockfile 时选错包管理器。
如果当前包不属于任何 workspace,builder 只处理当前包版本,不会修改父目录或其他项目。如果属于 workspace,构建成功后会查找所有名称依赖当前包的其他 package,并更新以下字段:
位于 git submodule 中的包也会继续向上检查;只有上级 workspace 的 packages
pattern 实际包含当前包时,才会把它当作该 workspace 的成员并同步消费方。未被 pattern 包含的独立子模块仍按非 workspace 包处理。
dependencies;devDependencies;peerDependencies;optionalDependencies。
更新时会尽量保留原有依赖意图,例如 ^1.2.3 变为 ^1.3.0、~1.2.3 变为
~1.3.0、workspace:^1.2.3 变为 workspace:^1.3.0。file:、link:
和未解析的特殊协议不会被强行改写。
对于 catalog: 依赖,consumer 的 catalog: 声明保持不变,builder 会更新 pnpm-workspace.yaml
中对应的 catalog
或命名 catalog 版本。只要 manifest 或 catalog 发生变化,并且检测到 lockfile,builder 就会调用对应包管理器刷新 lockfile。
workspace 同步控制
# 升级当前包并同步所有 workspace 消费方
pnpm exec ldesign-builder build --version-bump minor
# 只升级当前包,不修改其他 package.json 或 catalog
pnpm exec ldesign-builder build --version-bump minor --no-workspace-update
# 更新 manifest/catalog,但不执行 pnpm/npm/yarn/bun lockfile 刷新
pnpm exec ldesign-builder build --version-bump minor --no-lockfile-update
--no-workspace-update 和 --no-lockfile-update
只影响提交阶段,不会跳过构建,也不会阻止当前包版本在构建前写入。构建或同步失败时,builder 会优先恢复文件,避免出现“当前包已经升级但消费方没有同步”的半完成状态。
dry-run 与 watch
--dry-run 只解析配置并显示版本规划,不写入 package.json、workspace
manifest、catalog 或 lockfile:
pnpm exec ldesign-builder build --version-bump minor --dry-run --print-config
build --watch
是长驻监听模式,不会启动一次性版本事务,也不会在每次文件变化时重复升级版本。需要升级版本时,先完成一次普通
build,确认构建和 workspace 同步成功后,再启动 watch:
pnpm exec ldesign-builder build --version-bump minor
pnpm exec ldesign-builder build --watch
2. 使用配置文件
创建 builder.config.ts:
import { defineConfig } from '@composy/builder'
export default defineConfig({
bundler: 'rolldown',
libraryType: 'react',
input: 'src/index.ts',
output: {
es: {
dir: 'es',
},
esm: {
dir: 'esm',
preserveLessSource: true,
},
cjs: {
dir: 'lib',
},
umd: {
dir: 'dist',
name: 'DemoLibrary',
},
},
packageUpdate: {
enabled: true,
},
postBuildValidation: {
enabled: true,
},
})
然后执行:
pnpm exec ldesign-builder build --config builder.config.ts
输出目录语义
当前包围绕以下四类目录组织产物:
es/:编译后的主 ESM 产物,默认也是module与类型入口的首选目录。esm/:保留结构或保留样式源码的辅助 ESM 目录,适合 less 等场景。lib/:CJS 产物目录。dist/:UMD 产物目录,同时可放置聚合样式文件。
如果你使用 legacy 形式:
output: {
dir: 'dist',
format: ['esm', 'cjs'],
}
它会被视为“单目录多格式输出”。如果希望对不同格式分别配置 dir、input、dts、preserveLessSource
等能力,应改用 output.es / output.esm / output.cjs / output.umd 分支配置。
当 UMD 包还需要发布独立 Worker 等浏览器资产时,在同一个 output.umd 中配置
entries;每个 entry 会使用同一套 builder/Rolldown 配置生成常规和压缩版本:
output: {
umd: {
input: 'src/index.ts',
fileName: 'index.js',
name: 'DemoLibrary',
entries: [
{
input: 'src/workers/demo.worker.ts',
fileName: 'demo.worker.js',
name: 'DemoWorker',
},
],
},
}
CLI
每次 ldesign-builder 命令都会在当前项目创建完整执行日志:
.ldesign/.logs/builder/<ISO 时间>-<pid>.log
日志会记录命令、构建输出、错误堆栈、退出码和耗时;常见敏感命令参数会自动脱敏,日志写入失败不会影响原构建流程。
常用命令如下:
ldesign-builder build:执行构建。ldesign-builder build --profile ci:应用构建预设后执行构建。ldesign-builder build --print-config:打印最终合并后的配置。ldesign-builder build --dry-run:只预览构建计划,不执行打包。ldesign-builder watch --profile development:使用指定预设监听并增量构建。ldesign-builder doctor --json:输出可脚本消费的项目诊断结果。ldesign-builder doctor --strict --artifacts:在发布前严格检查 package 入口、exports 与构建产物。ldesign-builder doctor --fail-on-warnings --report reports/builder-doctor.json:将 warning 也视为失败,并写入 JSON 诊断报告。ldesign-builder analyze:输出构建分析信息。ldesign-builder init:生成或初始化配置。ldesign-builder examples:批量执行示例项目构建。ldesign-builder typecheck:执行类型检查辅助流程。ldesign-builder size:查看体积信息。ldesign-builder visualize:输出可视化相关分析。
查看完整命令帮助:
doctor --json 与 doctor --report 会输出 metadata.layouts.configOutputDirs、
metadata.layouts.packageOutputDirs 和
metadata.layouts.effectiveOutputDirs,用于在 CI 中区分 builder 配置输出、package.json
推断输出和合并后的有效发布目录。
pnpm exec ldesign-builder --help
build 版本与 workspace 参数速查
| 参数 | 作用 | 默认行为 |
|---|---|---|
--version-bump <方案或版本> |
非交互指定 patch、minor、major、alpha、beta、rc、none 或完整 SemVer |
TTY 中询问;非 TTY 保持当前版本 |
--no-version-prompt |
跳过版本询问 | 保持当前版本 |
--no-workspace-update |
不更新 workspace 消费方和 catalog | 构建成功后自动同步 |
--no-lockfile-update |
不刷新 pnpm/npm/yarn/bun lockfile | 有 manifest/catalog 变化时自动刷新 |
--dry-run |
只显示配置和版本计划,不写文件或执行打包 | 仅预览 |
--watch |
进入长驻监听模式 | 跳过一次性版本事务 |
推荐的发布构建顺序是:先执行一次带 --version-bump
的普通构建,确认 workspace 同步和 lockfile 更新成功,再执行 build --watch
或其他后续开发命令。若发布流程由外部版本工具管理,可使用 --version-bump none 或
--no-version-prompt 明确关闭 builder 的版本写入。
编程式 API
最常用的公开 API 包括:
LibraryBuilderConfigManagerStrategyManagerPluginManagerPostBuildValidatordefineConfigautoConfigpresetsProjectAnalyzer
示例:
import { LibraryBuilder } from '@composy/builder'
const builder = new LibraryBuilder({
config: {
input: 'src/index.ts',
output: {
es: { dir: 'es' },
cjs: { dir: 'lib' },
},
},
})
await builder.build()
缓存依赖失效
使用 BuildCacheManager.setWithDependencies() 写入构建缓存时,依赖路径会同时保存到缓存条目的
metadata.dependencies,并在内存中建立依赖追踪。后续调用 get(key)
不需要再次传入依赖列表;只要任一依赖文件的 mtime
晚于缓存创建时间,缓存就会被判定为失效并删除。该依赖元数据会随 .cache
文件持久化,因此进程重启后仍然有效。
await cache.setWithDependencies('bundle:src/index.ts', result, ['src/index.ts', 'src/shared.ts'])
// 依赖发生变化时返回 null,并清理对应缓存
const cached = await cache.get('bundle:src/index.ts')
如果调用方只在单次读取时拥有依赖列表,也可以继续使用 get(key, dependencies)
覆盖条目内记录的依赖集合。
样式处理与产物校验
构建完成后,builder 会按配置执行两类补链逻辑:
-
样式补链
- 编译 less/scss/sass 到目标目录
- 为组件库生成
style/index.js、style/css.js - 在
dist/中生成聚合 CSS
-
产物自检
- 检查入口 JS/CJS 是否存在
- 检查声明文件是否落盘
- 检查 UMD 产物与聚合样式
- 解析输出 JS,快速发现语法层面的坏包
默认情况下,自检失败会以 warning 形式反馈;需要阻断构建时,再显式开启
postBuildValidation.failOnError。
开发脚本
当前仓库脚本与发布链已经统一到 @composy/pack:
pnpm run build
pnpm run build:types
pnpm run type-check
pnpm run lint:check
pnpm run format:check
其中:
build会使用@composy/pack编译src/**/*.ts对应的源码文件,输出esm、cjs与d.tsbuild:types会通过tsc -p tsconfig.build.json单独补齐声明文件lint:check当前聚焦src/**/*.ts、.ldesign下的 JS/TS 配置与脚本,以及根转发配置
权威工程配置集中在 .ldesign/:pack.config.mjs 是 @composy/pack 构建入口, eslint.config.js
和 tsconfig*.json 是 ESLint/TypeScript 配置。保留的 .ldesign/tsup.config.mjs
只转发到 pack 配置;根目录同名 TypeScript/ESLint 文件以及 tsconfig.build.json、
tsconfig.dts.json 是为工具自动发现和现存脚本保留的薄 shim。
文档
更细分的使用说明仍保留在 docs/:
当前包维护约定
- 构建配置统一走
.ldesign/pack.config.mjs - 发布产物统一输出到
dist/ - 质量校验以
type-check、lint:check、build为准 - 会话结束前应更新
AGENTS.md,记录背景、发现、进度与待办
License
MIT
通过 @composy/cli 统一接入
- 接入类型:
bin - 统一命令:
ldesign builder - 命令别名:
ldesign-builder - 包内原生 bin:
ldesign-builder
当前包通过独立 bin 接入,统一命令会转发到包自身 CLI。
pnpm add -D @composy/cli
ldesign builder --help
ldesign tools run builder --help
2026-10 构建可靠性与低内存优化
本次源码级增强的修复清单、并发控制、缓存失效策略、独立 smoke 校验和验证限制参见 Builder 强化审计报告。
Worker 线程池与构建监听的正确性说明
- WorkerPool 默认按需创建线程,最多使用 8 个可用 CPU 并行度(可用
maxWorkers自定义);minWorkers默认 0,idleTimeout可在空闲时回收额外线程。terminate()会拒绝进行中和排队任务。enablePriority默认开启,优先级高的任务先运行,同级按入队顺序执行。 - 统一适配器不再使用仅凭时间戳命中的第二层
BuildResult缓存,以免源码变化后返回旧结果;由底层打包器管理其经过文件校验的缓存。明确指定cache:false时会传递给具体打包器。 - 不再隐式更改用户传入的
treeshake.moduleSideEffects、output.compact或output.sourcemap。不同引擎依各自约定执行多格式输出,SWC 使用顺序构建。 - 可以运行
npm run test:smoke:builder:round6检查这轮独立行为回归。这不是完整工作区的编译或真实 Rollup/Rolldown 集成测试。
第七轮构建适配器校验(2026-10-10)
新增 esbuild Sass/SCSS/Less 预处理、SWC 输出路径隔离与有界并发、动态 glob 监听。独立回归:npm run test:smoke:builder:round7。详细修改、限制和完整工程依赖请参阅 docs/DEEP_SOURCE_AUDIT_ROUND_7.md。
Related Packages
Zero-config frontend launcher built on Vite with dev, build, preview, config, en...
A Rust+Zig bundler with incremental computation, JS plugins, and Rollup-quality...
Auto-generate framework wrappers (React, Vue, Svelte, Angular, Solid, Preact) an...
Version History
| Version | Released | License |
|---|---|---|
| 0.1.0 | MIT | |
| 0.0.1 | MIT |