tsdown-migrate

tsdown-migrate

热门

将 TypeScript 库项目从 tsup 迁移到 tsdown。提供完整的选项映射、配置转换规则、默认值差异以及不支持的选项替代方案,使 AI 代理能够智能地执行迁移。

4238Star
184Fork
更新于 2026/8/28
SKILL.md
只读
名称
tsdown-migrate
描述

将 TypeScript 库项目从 tsup 迁移到 tsdown。提供完整的选项映射、配置转换规则、默认值差异以及不支持的选项替代方案,使 AI 代理能够智能地执行迁移。

从 tsup 迁移到 tsdown

供 AI 代理将 tsup 项目迁移到 tsdown(基于 Rolldown 的库打包器)的知识库。

目标版本:两阶段迁移

tsdown v0.23 移除了所有先前已弃用的 tsup 兼容选项——bundleoutExtensionpublicDirremoveNodeProtocolinjectStyleskipNodeModulesBundle 不再被识别。它们会导致 TypeScript 类型检查失败,并且在运行时被静默忽略,因此在 v0.23+ 上遗漏映射会产生错误输出而没有任何错误提示。因此,直接迁移到 v0.23+ 是不安全的。tsdown v0.22.14 是最后一个仍然接受这些选项并带有弃用警告的版本,使其成为安全的迁移检查点。请按两个阶段进行迁移:

  1. 阶段 1——在 tsdown@0.22.14 上迁移:安装 tsdown@0.22.14,根据下面的表格迁移配置,运行构建,并通过将每个标记的 tsup 选项映射到其真正的 tsdown 等效项来解决每个弃用警告。警告是完整性检查——直到构建产生零警告,迁移才算完成。
  2. 阶段 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 项目:

  1. 重命名配置文件tsup.config.*tsdown.config.*
  2. 更新导入'tsup''tsdown'
  3. 应用选项映射:根据下面的表格重命名/转换选项
  4. 保留 tsup 默认值:显式设置不同的选项(format、clean、dts、target)
  5. 更新 package.json:依赖项(阶段 1:tsdown@0.22.14)、脚本、根配置字段
  6. 移除不支持的选项:在有替代方案的地方替换
  7. 在 0.22.14 上测试构建:运行 tsdown 并解决每个弃用警告——需要零警告
  8. 升级到最新的 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

导入和标识符更改

// 之前
import { defineConfig } from 'tsup'

// 之后
import { defineConfig } from 'tsdown'

替换所有标识符:tsuptsdownTSUPTSDOWN

选项映射

属性重命名

tsup tsdown 备注
entryPoints entry 在 tsup 中本身也已弃用
cjsInterop cjsDefault CJS 默认导出处理
esbuildPlugins plugins 现在使用 Rolldown/Unplugin 插件
outExtension outExtensions 自定义输出扩展名
publicDir copy 将静态文件复制到输出
bundle: true (移除) 打包是默认行为
bundle: false unbundle: true 保留文件结构
removeNodeProtocol: true nodeProtocol: 'strip' 去除 node: 前缀
injectStyle: true css: { inject: true } CSS 注入
injectStyle: false (移除) 默认行为
skipNodeModulesBundle deps: { neverBundle: true } 外部化所有依赖项

tsdown v0.23+ 不再识别任何旧名称——始终使用新名称。兼容选项(outExtensionskipNodeModulesBundlepublicDirbundleremoveNodeProtocolinjectStyle)在 v0.22.14 之前(含)接受并带有弃用警告,并在 v0.23 中完全移除;在 v0.23+ 上,遗留选项会被静默忽略,而不是报错,因此构建会在没有警告的情况下出错。这就是为什么阶段 1 在 v0.22.14 上运行,每个遗留选项都会被标记。

已弃用但仍接受

externalnoExternal 是 tsdown v0.23 仍然接受的唯一 tsup 选项名称。它们会发出弃用警告,将在未来版本中移除,并且不能与其替代品组合使用(将 externaldeps.neverBundle 混合,或将 noExternaldeps.alwaysBundle 混合,会抛出错误)。始终使用替代品。

tsup(已弃用) tsdown(首选) 备注
external: [...] deps: { neverBundle: [...] } 移至 deps 命名空间
noExternal: [...] deps: { alwaysBundle: [...] } 移至 deps 命名空间

输出文件名差异

对于 IIFE 构建,tsdown 生成类似 [name].iife.js 的名称,而 tsup 通常生成 [name].global.jsoutExtensions 可以自定义扩展名或后缀,但不会移除内置的 .iife.umd 段。使用 outputOptions.entryFileNames: '[name].global.js' 保留旧的 IIFE 文件名。

依赖项命名空间移动

依赖项配置移至 deps 命名空间下。如果同时存在 externalnoExternal,则合并为单个 deps 对象:

// 之前(tsup)
export default defineConfig({
  external: ['react'],
  noExternal: ['lodash-es'],
})

// 之后(tsdown)
export default defineConfig({
  deps: {
    neverBundle: ['react'],
    alwaysBundle: ['lodash-es'],
  },
})

tsdown 还添加了 deps.onlyBundle(允许打包的包白名单)——tsup 没有等效项。

tsdown v0.23+ 中的依赖项处理默认值:

  • dependenciespeerDependenciesoptionalDependencies 默认全部外部化(tsup 仅外部化 dependenciespeerDependencies,因此迁移后 optionalDependencies 可能会从打包变为外部化)。
  • deps.resolveDepSubpath(解析外部化包中没有 exports 字段的子路径导入)默认禁用

插件导入转换

// 之前(tsup - esbuild 插件)
import plugin from 'unplugin-example/esbuild'

// 之后(tsdown - Rolldown 插件)
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 迁移

脚本

将所有脚本命令中的 tsuptsup-node 替换为 tsdown

// 之前
{
  "scripts": {
    "build": "tsup src/index.ts",
    "dev": "tsup --watch"
  }
}

// 之后
{
  "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

// 之前
{ "tsup": { "entry": ["src/index.ts"] } }

// 之后
{ "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: trueattw: true 检查包并验证类型正确性
可执行文件 exe: true 打包为 Node.js 独立可执行文件(SEA)
DevTools devtools: true Vite DevTools 集成用于包分析
钩子 hooks: { 'build:done': ... } 生命周期钩子:build:preparebuild:beforebuild:done
CSS 模块 css: { modules: { ... } } .module.css 文件提供作用域类名
通配符导入 globImport: true 支持 import.meta.glob(Vite 风格)

有关详细比较,请参阅 guide-differences-detailed.md

参考

主题 描述 参考
选项映射 每个选项转换的完整前后对比 guide-option-mappings
详细差异 架构、特性、兼容性比较 guide-differences-detailed
package.json 依赖项、脚本和配置字段迁移 guide-package-json

迁移检查清单

执行迁移时使用此检查清单:

- [ ] 重命名 tsup.config.* → tsdown.config.*
- [ ] 将导入从 'tsup' 更新为 'tsdown'
- [ ] 将 tsup/TSUP 标识符替换为 tsdown/TSDOWN
- [ ] 应用属性重命名(cjsInterop→cjsDefault、esbuildPlugins→plugins、outExtension→outExtensions、publicDir→copy、bundle→unbundle、removeNodeProtocol→nodeProtocol、injectStyle→css.inject)
- [ ] 将 external/noExternal 移至 deps 命名空间,将 skipNodeModulesBundle 替换为 `deps.neverBundle: true`
- [ ] 将 unplugin 导入从 /esbuild 更新为 /rolldown
- [ ] 设置显式默认值以保留 tsup 行为(format、clean、dts、target)
- [ ] 移除不支持的选项(splitting、metafile、swc 等)
- [ ] 更新 package.json 脚本(tsup→tsdown)
- [ ] 更新 package.json 依赖项(阶段 1:tsdown@0.22.14)
- [ ] 如果存在,重命名根级别的 tsup 配置字段
- [ ] 在 0.22.14 上运行 tsdown 并解决每个弃用警告(需要零警告)
- [ ] 升级到最新的 tsdown(^0.23.0 或更新版本)并再次验证构建
- [ ] 向用户建议新的 tsdown 特性