关于 tsdown-migrate
tsdown-migrate 是供 AI Agent 将项目从 tsup 迁移到 tsdown 的知识库,涵盖分阶段升级、选项映射、默认值变化和不支持的设置。
主要功能
- 01分阶段迁移指引
- 02tsup 选项映射
- 03默认值差异参考
- 04不支持选项说明
- 05软件包与脚本迁移
适用场景
- 01迁移 tsup 配置
- 02核对构建默认值变化
- 03查找已移除选项的替代项
- 04更新软件包脚本与依赖
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rolldown/ tsdown --skill tsdown-migrate安装后在 Claude Code 中输入/tsdown-migrate确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdreferences/guide-differences-detailed.mdguide-option-mappings.mdguide-package-json.md详细介绍
从 tsup 迁移到 tsdown
帮助 AI Agent 将 tsup 项目迁移到 tsdown(由 Rolldown 驱动的库打包工具)的知识库。
目标版本:两阶段迁移
tsdown v0.23 移除了所有此前已弃用的 tsup 兼容选项——bundle、outExtension、publicDir、removeNodeProtocol、injectStyle 和 skipNodeModulesBundle 均不再受识别。这些选项会导致 TypeScript 类型检查失败,并且在运行时被静默忽略,因此在 v0.23+ 中漏掉映射会导致输出错误,却不会报错。因此,直接迁移到 v0.23+ 并不安全。tsdown v0.22.14 是最后一个仍接受这些选项、并会为每个选项发出弃用警告的版本,因此是安全的迁移检查点。请分两个阶段进行迁移:
- 阶段 1 — 在
[email protected]上迁移:安装[email protected],根据下表迁移配置,运行构建,并通过映射每个被标记的 tsup 选项到其对应的 tsdown 选项来解决所有弃用警告。这些警告是检查迁移是否完整的依据——只有构建产生零条警告,迁移才算完成。 - 阶段 2 — 升级到最新的 tsdown(
^0.23.0或更高版本):仅在 0.22.14 上构建无警告后进行。由于配置不再使用任何已移除的兼容选项,v0.23+ 的静默忽略行为就不再构成风险。
运行时要求
运行 tsdown 需要 Node.js ^22.18.0 || ^24.11.0 || >=26.0.0(仅构建时需要)——也就是说,需要 Node.js 22.18+、24.11+ 或 26+。不支持奇数主版本和已结束生命周期的版本系列(例如 Node.js 23、25)。打包后的输出仍可通过 target 选项面向较低版本的 Node.js,因此此前用 tsup 支持 Node.js 18 / 20 的库,迁移后仍可继续支持这些版本。
支持 Node.js 18 / 20 时,推荐的工作流:
- 在 CI 中使用 Node.js 22+ 构建,并设置显式的
target,例如'node18'或'node20'。 - 在需要支持的较低版本 Node.js 上测试构建输出(或打包后的 tarball)。
适用场景
- 将项目从 tsup 迁移到 tsdown
- 了解 tsup 和 tsdown 选项之间的差异
- 检查或修复迁移后的配置问题
- 为用户提供 tsup→tsdown 兼容性建议
迁移概览
按照以下步骤迁移 tsup 项目:
- 重命名配置文件:
tsup.config.*→tsdown.config.* - 更新导入:
'tsup'→'tsdown' - 应用选项映射:根据下表重命名或转换选项
- 保留 tsup 默认行为:显式设置存在差异的选项(format、clean、dts、target)
- 更新 package.json:依赖项(阶段 1:
[email protected])、脚本和根配置字段 - 移除不支持的选项:在有替代方案时使用替代方案
- 在 0.22.14 上测试构建:运行
tsdown并解决所有弃用警告——必须达到零条警告 - 升级到最新的 tsdown(
^0.23.0或更高版本),并再次验证构建
配置文件迁移
文件重命名
| tsup | tsdown |
|---|---|
tsup.config.ts | tsdown.config.ts |
tsup.config.cts | tsdown.config.cts |
tsup.config.mts | tsdown.config.mts |
tsup.config.js | tsdown.config.js |
tsup.config.cjs | tsdown.config.cjs |
tsup.config.mjs | tsdown.config.mjs |
tsup.config.json | tsdown.config.json |
导入和标识符变更
// Before
import { defineConfig } from 'tsup'
// After
import { defineConfig } from 'tsdown'
替换所有标识符:tsup → tsdown,TSUP → TSDOWN。
选项映射
属性重命名
| tsup | tsdown | 说明 |
|---|---|---|
entryPoints | entry | 在 tsup 本身中也已弃用 |
cjsInterop | cjsDefault | CJS 默认导出处理 |
esbuildPlugins | plugins | 现在使用 Rolldown/Unplugin 插件 |
outExtension | outExtensions | 自定义输出扩展名 |
publicDir | copy | 将静态文件复制到输出目录 |
bundle: true | (remove) | 默认会打包 |
bundle: false | unbundle: true | 保留文件结构 |
removeNodeProtocol: true | nodeProtocol: 'strip' | 移除 node: 前缀 |
injectStyle: true | css: { inject: true } | CSS 注入 |
injectStyle: false | (remove) | 默认行为 |
skipNodeModulesBundle | deps: { neverBundle: true } | 将所有依赖设为外部依赖 |
tsdown v0.23+ 不识别任何旧名称——务必使用新名称。兼容选项(outExtension、skipNodeModulesBundle、publicDir、bundle、removeNodeProtocol、injectStyle)在 v0.22.14 及更早版本中仍可使用,但会发出弃用警告;这些选项在 v0.23 中已被彻底移除;在 v0.23+ 中,遗留选项会被静默忽略,而不是报错,因此构建可能会出错且没有警告。这就是为什么第 1 阶段使用 v0.22.14,在该版本中每个遗留选项都会被标记。
已弃用但仍可使用的选项
external 和 noExternal 是 tsdown v0.23 仍接受的仅有的 tsup 选项名称。它们会发出弃用警告,并将在未来版本中移除;也不能与其替代项同时使用(将 external 与 deps.neverBundle 混用,或将 noExternal 与 deps.alwaysBundle 混用,都会报错)。务必使用替代项。
| tsup(已弃用) | tsdown(推荐) | 说明 |
|---|---|---|
external: [...] | deps: { neverBundle: [...] } | 移至 deps 命名空间 |
noExternal: [...] | deps: { alwaysBundle: [...] } | 移至 deps 命名空间 |
输出文件名差异
对于 IIFE 构建,tsdown 会生成 [name].iife.js 这样的文件名,而 tsup 通常会生成 [name].global.js。outExtensions 可以自定义扩展名或后缀,但不会移除内置的 .iife 或 .umd 部分。使用 outputOptions.entryFileNames: '[name].global.js' 可保留旧版 IIFE 文件名。
依赖命名空间迁移
依赖配置已移至 deps 命名空间。如果同时存在 external 和 noExternal,请合并到同一个 deps 对象中:
// Before (tsup)
export default defineConfig({
external: ['react'],
noExternal: ['lodash-es'],
})
// After (tsdown)
export default defineConfig({
deps: {
neverBundle: ['react'],
alwaysBundle: ['lodash-es'],
},
})
tsdown 还新增了 deps.onlyBundle(允许打包的程序包白名单)——tsup 中没有对应选项。
tsdown v0.23+ 中的依赖处理默认行为:
- 默认会将
dependencies、peerDependencies和optionalDependencies全部设为外部依赖(tsup 只会将dependencies和peerDependencies设为外部依赖,因此迁移后optionalDependencies可能会从打包变为外部依赖)。 - 默认禁用
deps.resolveDepSubpath(解析没有exports字段的外部依赖程序包的子路径导入)。
插件导入转换
// Before (tsup - esbuild plugins)
import plugin from 'unplugin-example/esbuild'
// After (tsdown - Rolldown plugins)
import plugin from 'unplugin-example/rolldown'
所有 unplugin-*/esbuild 导入都应改为 unplugin-*/rolldown。
如需查看每种转换的完整迁移前后示例,请参阅 guide-option-mappings.md。
默认值差异
tsdown 更改了 tsup 的若干默认值。迁移时,请显式设置这些选项以保留 tsup 的行为,然后让用户决定是否采用新的默认值。
| 选项 | tsup 默认值 | tsdown 默认值 | 迁移操作 |
|---|---|---|---|
format | 'cjs' | 'esm' | 设置 format: 'cjs' 以保留原行为 |
clean | false | true | 设置 clean: false 以保留原行为 |
dts | false | 如果 package.json 中包含 types/typings,则自动启用 | 设置 dts: false 以保留原行为 |
target | (无) | 自动读取 package.json 中的 engines.node | 设置 target: false 以保留原行为 |
迁移后,建议用户评估这些选项——tsdown 的默认值通常更好:
- ESM 是现代标准
- 清理输出可避免残留文件
- 从 package.json 自动生成 DTS 可减少配置
- 从 engines.node 自动设置 target 可确保一致性
不支持的选项
这些 tsup 选项在 tsdown 中没有直接对应项。请移除它们并告知用户。
| tsup 选项 | 状态 | 替代方案 |
|---|---|---|
splitting | 始终启用 | 移除——在 tsdown 中无法禁用代码拆分 |
metafile | 不可用 | 建议使用 devtools: true 进行 Vite DevTools 包分析 |
swc | 不支持 | 移除——tsdown 使用 oxc 进行转换(内置) |
experimentalDts | 不支持 | 改用 dts 选项 |
legacyOutput | 不支持 | 移除——没有替代方案 |
plugins(tsup 实验性功能) | 不兼容 | 手动迁移到 Rolldown 插件;tsup 的插件 API 与 Rolldown 的不同 |
Package.json 迁移
脚本
在所有脚本命令中,将 tsup 和 tsup-node 替换为 tsdown:
// Before
{
"scripts": {
"build": "tsup src/index.ts",
"dev": "tsup --watch"
}
}
// After
{
"scripts": {
"build": "tsdown src/index.ts",
"dev": "tsdown --watch"
}
}
依赖项
| 位置 | 操作 |
|---|---|
dependencies.tsup | 重命名为 dependencies.tsdown |
devDependencies.tsup | 重命名为 devDependencies.tsdown |
optionalDependencies.tsup | 重命名为 optionalDependencies.tsdown |
peerDependencies.tsup | 重命名为 peerDependencies.tsdown |
peerDependenciesMeta.tsup | 重命名为 peerDependenciesMeta.tsdown |
根配置字段
如果 package.json 中有根级别的 tsup 字段(内联配置),请将其重命名为 tsdown:
// Before
{ "tsup": { "entry": ["src/index.ts"] } }
// After
{ "tsdown": { "entry": ["src/index.ts"] } }
有关 package.json 示例的详细信息,请参阅 guide-package-json.md。
tsdown 新功能
迁移后,建议用户了解这些 tsdown 独有功能:
| 功能 | 配置 | 描述 |
|---|---|---|
| Node 协议 | nodeProtocol: true | 'strip' | 为内置导入添加或移除 node: 前缀 |
| 工作区 | workspace: 'packages/*' | 在 monorepo 中构建多个包 |
| 包导出 | exports: true | 在 package.json 中自动生成 exports 字段 |
| 包验证 | publint: true、attw: true | 检查包并验证类型正确性 |
| 可执行文件 | exe: true | 打包为 Node.js 独立可执行文件(SEA) |
| DevTools | devtools: true | 集成 Vite DevTools 以分析包 |
| 钩子 | hooks: { 'build:done': ... } | 生命周期钩子:build:prepare、build:before、build:done |
| CSS 模块 | css: { modules: { ... } } | 为 .module.css 文件生成作用域类名 |
| Glob 导入 | globImport: true | 支持 import.meta.glob(Vite 风格) |
有关详细对比,请参阅 guide-differences-detailed.md。
参考资料
| 主题 | 描述 | 参考资料 |
|---|---|---|
| 选项映射 | 每个选项转换前后的完整对照 | guide-option-mappings |
| 详细差异 | 架构、功能、兼容性对比 | guide-differences-detailed |
| Package.json | 依赖项、脚本和配置字段迁移 | guide-package-json |
迁移清单
执行迁移时,请使用此清单:
- [ ] Rename tsup.config.* → tsdown.config.*
- [ ] Update import from 'tsup' to 'tsdown'
- [ ] Replace tsup/TSUP identifiers with tsdown/TSDOWN
- [ ] Apply property renames (cjsInterop→cjsDefault, esbuildPlugins→plugins, outExtension→outExtensions, publicDir→copy, bundle→unbundle, removeNodeProtocol→nodeProtocol, injectStyle→css.inject)
- [ ] Move external/noExternal into deps namespace, replace skipNodeModulesBundle with `deps.neverBundle: true`
- [ ] Update unplugin imports from /esbuild to /rolldown
- [ ] Set explicit defaults to preserve tsup behavior (format, clean, dts, target)
- [ ] Remove unsupported options (splitting, metafile, swc, etc.)
- [ ] Update package.json scripts (tsup→tsdown)
- [ ] Update package.json dependencies (Stage 1: [email protected])
- [ ] Rename root-level tsup config field if present
- [ ] Run tsdown on 0.22.14 and resolve every deprecation warning (zero warnings required)
- [ ] Upgrade to the latest tsdown (^0.23.0 or newer) and verify the build again
- [ ] Suggest new tsdown features to the user