首页
/ tsdown `exe` 选项实战:把 TypeScript CLI 打包成跨平台独立可执行文件

tsdown `exe` 选项实战:把 TypeScript CLI 打包成跨平台独立可执行文件

2026-09-07 17:39:23作者:瞿蔚英Wynne

本文以 airi 仓库内置的 tsdown 技能文档 option-exe.md 为主体,系统讲解 tsdown 实验性的 exe 选项:基于 Node.js 单可执行应用(Single Executable Applications, SEA)技术,把一份 TypeScript 入口文件打包为无需用户预装 Node.js 环境的独立可执行文件,并支持通过 @tsdown/exe 在一台机器上交叉构建 Linux / macOS / Windows 三种平台的产物。读完后你将掌握 exe 选项的启用方式、对构建行为的自动调整、seaConfig 各参数含义、跨平台目标配置与缓存机制,以及 airi 这类大型 monorepo 中 tsdown 工程体系的落地背景。

背景:SEA 与 airi 中的 tsdown 体系

tsdown 是基于 Rolldown 的 TypeScript/JavaScript 库打包器,其技能总览见 SKILL.mdexe 是其"输出增强"能力之一,文档明确标注为 [experimental] 实验特性:它利用 Node.js 官方提供的 Single Executable Applications 机制,把打包后的 JS 产物注入 Node.js 二进制内部,产出一个独立可执行文件。

在 airi 仓库中,tsdown 已通过 pnpm catalog 统一管理版本(根 package.json"tsdown": "catalog:"pnpm-lock.yaml 锁定为 0.22.14),并且至少 29 个子包各自携带 tsdown.config.ts,例如 packages/better-ws/tsdown.config.tsservices/computer-use-mcp/tsdown.config.ts。从这些配置的结构看,airi 目前的产出仍以库分发(entry + dts + 多入口 exports)为主,exe 能力尚未在任何包的配置中启用——但像 computer-use-mcp 的 bin/runner 入口这类带 bin/ 脚本的 CLI 工具,正是 exe 选项的典型适用对象。

前置要求

启用 exe 有两条硬性约束,来自文档 "Requirements" 一节:

  • Node.js >= 25.5.0;若要产出 ESM 格式的二进制(而不是 CJS),需要 >= 25.7.0
  • 不支持在 Bun 或 Deno 运行时下构建(SEA 注入依赖 Node.js 官方二进制文件本身)。

这与 tsdown 本身的运行时要求是两回事:tsdown 运行只需要 Node.js >= 22.18.0(见 SKILL.md 的 "Runtime Requirement"),而 exe 选项因为要操作目标平台的 Node.js 二进制,把门槛抬升到了 25.x。

基础用法

最小配置只需两个字段:

export default defineConfig({
  entry: ['src/cli.ts'],
  exe: true,
})

entry 必须收敛为单一入口(原因见下文"启用后的行为变化")。运行 tsdown 后,dist/ 下会产出一个与入口同名的可执行文件(Windows 下自动追加 .exe 扩展名)。

启用 exe 后的自动行为变化

这是文档中容易被忽视、却直接影响构建产物的一节。开启 exe 后 tsdown 会调整以下构建行为,理解它们能帮你预判产物差异:

变化项 说明
默认输出格式 esm 变为 cjs(除非运行环境 Node.js >= 25.7.0,此时可保持 ESM)
dts 声明文件生成 默认禁用——可执行文件面向最终用户,不需要 .d.ts
代码分割 禁用——SEA 二进制只能注入单份 JS payload,无法运行时再按 chunk 加载
入口数量 仅支持单入口,多入口会违反 SEA 注入模型
Legacy CJS 警告 被静默压制(因为 CJS 正是默认产物格式)

从源码结构看,这些约束都源自 SEA 的注入模型:可执行文件内部是一份完整的、随进程一次性加载的 JS bundle,因此"单入口、不分割、CJS/ESM 二选一"都是结构性必然,而非 tsdown 的额外限制。

高级配置:ExeOptionsSeaConfig

需要定制时,exe 接受对象形式:

export default defineConfig({
  entry: ['src/cli.ts'],
  exe: {
    fileName: 'my-tool',
    seaConfig: {
      disableExperimentalSEAWarning: true,
      useCodeCache: true,
      useSnapshot: false,
    },
  },
})

ExeOptions 完整字段:

选项 类型 说明
seaConfig Omit<SeaConfig, 'main' | 'output' | 'mainFormat'> Node.js SEA 注入配置;main / output / mainFormat 由 tsdown 托管,不允许覆盖
fileName string | ((chunk) => string) 自定义产物文件名(不含 .exe 与平台后缀,后缀由工具链追加)
targets ExeTarget[] 跨平台构建目标(需要额外安装 @tsdown/exe

seaConfig 透传给 Node.js SEA 流程,常用参数:

选项 类型 默认值 说明
disableExperimentalSEAWarning boolean true 关闭 SEA 实验性警告
useSnapshot boolean false 使用 V8 快照,加速冷启动
useCodeCache boolean false 使用 V8 代码缓存
execArgv string[] - 追加传给 Node.js 的启动参数
execArgvExtension 'none' | 'env' | 'cli' 'env' 运行时如何扩展 execArgv
assets Record<string, string> - 需要一并嵌入二进制的静态资源

其中 useSnapshotuseCodeCache 都是针对启动性能的手段:快照把 V8 初始堆状态固化进二进制,代码缓存则持久化编译产物,二者按启动场景取舍即可。assets 则适合那些"随包携带、读取后不再变化"的小文件(如内嵌模板、默认配置),避免运行时去磁盘查找。

跨平台构建:@tsdown/exetargets

默认情况下 exe 只能构建当前平台的产物。若要在一台开发机上产出一整套分发物,先安装配套工具:

pnpm add -D @tsdown/exe

然后在配置中声明 targets

export default defineConfig({
  entry: ['src/cli.ts'],
  exe: {
    targets: [
      { platform: 'linux', arch: 'x64', nodeVersion: '25.7.0' },
      { platform: 'darwin', arch: 'arm64', nodeVersion: '25.7.0' },
      { platform: 'win', arch: 'x64', nodeVersion: '25.7.0' },
    ],
  },
})

ExeTarget 字段说明:

字段 类型 说明
platform 'win' | 'darwin' | 'linux' 目标操作系统(沿用 nodejs.org 的命名)
arch 'x64' | 'arm64' 目标 CPU 架构
nodeVersion string 目标 Node.js 版本(必须 >=25.7.0

构建时 tsdown 会下载目标平台对应的 Node.js 二进制、本地缓存、逐个完成 SEA 注入,最终产出带平台后缀的文件:

dist/
  cli-linux-x64
  cli-darwin-arm64
  cli-win-x64.exe

二进制缓存

下载来的目标平台 Node.js 二进制会缓存在系统缓存目录,避免重复网络请求:

  • macOS: ~/Library/Caches/tsdown/node/
  • Linux: ~/.cache/tsdown/node/
  • Windows: %LOCALAPPDATA%/tsdown/Caches/node/

airi 的 lockfile 中已经登记了 @tsdown/exe@0.22.14(作为 tsdown 0.22.14 的同版本 peer 依赖项出现在 pnpm-lock.yaml),说明当前 catalog 版本链路上该工具链是可即时启用的。

平台行为细节

三条来自 "Platform Notes" 的行为约定,分发前值得确认:

  • macOS:产物自动做 ad-hoc 代码签名,保证 Gatekeeper 下可以本地运行;
  • Windows.exe 扩展名自动追加,无需在 fileName 中手写;
  • 指定了 targetsseaConfig.executable 字段被忽略——因为目标二进制由 targets[].nodeVersion 统一下载决定,手动指定 executable 会造成版本冲突。

CLI 用法

不写配置文件时,--exe 标志可以直接走命令行(与 reference-cli.md--exe 条目的描述一致):

tsdown --exe
tsdown src/cli.ts --exe

CLI 方式下无法传 seaConfig 细节,适合快速验证;正式配置建议落回 tsdown.config.ts

在 airi monorepo 中落地的适用边界

exe 引入 airi 时,有几个基于仓库现状的判断点:

  1. 适用对象:带 bin/ 入口、希望用户零 Node 环境直接运行的工具最契合,例如 services/computer-use-mcp 这类已有 bin/runbin/runner 双入口的 MCP 服务。注意 exe 仅支持单入口,多 bin 场景需要拆成多份配置(可参照 SKILL.md "Multiple Configs" 的数组写法,为每个 bin 单独声明一条 exe 配置);
  2. 构建环境:CI 需要把构建机 Node 升到 25.5.0+(ESM 产物需 25.7.0+),这与仓库现有 target: 'node18' 之类的低版本运行目标不冲突——target 控制产物语法降级,nodeVersion 控制注入用的宿主二进制,两者独立;
  3. 产物定位exe 产物面向终端分发而非 npm 发布,dts 默认关闭符合预期;同一包若要兼顾"发 npm + 出二进制",仍应保留原有库配置,把 exe 配置单独成文件管理。

小结

exe 选项把 tsdown 从"npm 库打包器"延伸到"终端产物分发":单入口打包 + SEA 注入 + 跨平台 targets 构成了完整链路,代价是实验性状态、Node 25.x 的构建门槛,以及"单入口、不分割、默认 CJS"三项结构性约束。对于 airi 中的 CLI 型工具包,启用路径清晰——确认 Node 版本、安装 @tsdown/exe(跨平台时)、按上文配置即可;而它当前在仓库中尚属"已就绪未启用"的能力,lockfile 中同版本依赖的存在意味着随时可以按本文流程接入。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.79 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
390