|
| 1 | +# Executable |
| 2 | + |
| 3 | +:::warning Experimental |
| 4 | +The `exe` option is experimental and may change in future releases. |
| 5 | +::: |
| 6 | + |
| 7 | +tsdown can bundle your TypeScript/JavaScript code into a standalone executable using [Node.js Single Executable Applications](https://nodejs.org/api/single-executable-applications.html). The output is a native binary that runs without requiring Node.js to be installed. |
| 8 | + |
| 9 | +## Requirements |
| 10 | + |
| 11 | +- Node.js >= 25.5.0 (ESM support requires >= 25.7.0) |
| 12 | +- Not supported in Bun or Deno |
| 13 | + |
| 14 | +## Basic Usage |
| 15 | + |
| 16 | +```bash |
| 17 | +tsdown src/cli.ts --exe |
| 18 | +``` |
| 19 | + |
| 20 | +Or in your config file: |
| 21 | + |
| 22 | +```ts [tsdown.config.ts] |
| 23 | +export default defineConfig({ |
| 24 | + entry: ['src/cli.ts'], |
| 25 | + exe: true, |
| 26 | +}) |
| 27 | +``` |
| 28 | + |
| 29 | +When `exe` is enabled: |
| 30 | + |
| 31 | +- The default output format changes from `esm` to `cjs` (unless Node.js >= 25.7.0, which supports ESM) |
| 32 | +- Declaration file generation (`dts`) is disabled by default |
| 33 | +- Code splitting is disabled |
| 34 | +- Only single entry points are supported |
| 35 | + |
| 36 | +## Advanced Configuration |
| 37 | + |
| 38 | +You can pass an object to `exe` for more control: |
| 39 | + |
| 40 | +```ts [tsdown.config.ts] |
| 41 | +export default defineConfig({ |
| 42 | + entry: ['src/cli.ts'], |
| 43 | + exe: { |
| 44 | + fileName: 'my-tool', |
| 45 | + seaConfig: { |
| 46 | + disableExperimentalSEAWarning: true, |
| 47 | + useCodeCache: true, |
| 48 | + }, |
| 49 | + }, |
| 50 | +}) |
| 51 | +``` |
| 52 | + |
| 53 | +### `fileName` |
| 54 | + |
| 55 | +Custom output file name for the executable. Do not include `.exe`, platform suffixes, or architecture suffixes — they are added automatically. |
| 56 | + |
| 57 | +Can be a string or a function: |
| 58 | + |
| 59 | +```ts [tsdown.config.ts] |
| 60 | +export default defineConfig({ |
| 61 | + entry: ['src/cli.ts'], |
| 62 | + // string |
| 63 | + exe: { fileName: 'my-tool' }, |
| 64 | + // or function |
| 65 | + // exe: { fileName: (chunk) => `my-tool-${chunk.name}` }, |
| 66 | +}) |
| 67 | +``` |
| 68 | + |
| 69 | +### `seaConfig` |
| 70 | + |
| 71 | +Passes options directly to Node.js. See the [Node.js documentation](https://nodejs.org/api/single-executable-applications.html) for full details. |
| 72 | + |
| 73 | +| Option | Type | Default | Description | |
| 74 | +| ------------------------------- | -------------------------- | ------- | ------------------------------------ | |
| 75 | +| `disableExperimentalSEAWarning` | `boolean` | `true` | Disable the experimental warning | |
| 76 | +| `useSnapshot` | `boolean` | `false` | Use V8 snapshot for faster startup | |
| 77 | +| `useCodeCache` | `boolean` | `false` | Use V8 code cache for faster startup | |
| 78 | +| `execArgv` | `string[]` | — | Extra Node.js CLI arguments | |
| 79 | +| `execArgvExtension` | `'none' \| 'env' \| 'cli'` | `'env'` | How to extend execArgv at runtime | |
| 80 | +| `assets` | `Record<string, string>` | — | Assets to embed into the executable | |
| 81 | + |
| 82 | +## Cross-Platform Builds |
| 83 | + |
| 84 | +By default, `exe` builds for the current platform. To build executables for multiple platforms from a single machine, install the `@tsdown/exe` package and use the `targets` option: |
| 85 | + |
| 86 | +::: code-group |
| 87 | + |
| 88 | +```bash [pnpm] |
| 89 | +pnpm add -D @tsdown/exe |
| 90 | +``` |
| 91 | + |
| 92 | +```bash [npm] |
| 93 | +npm install -D @tsdown/exe |
| 94 | +``` |
| 95 | + |
| 96 | +```bash [yarn] |
| 97 | +yarn add -D @tsdown/exe |
| 98 | +``` |
| 99 | + |
| 100 | +::: |
| 101 | + |
| 102 | +```ts [tsdown.config.ts] |
| 103 | +export default defineConfig({ |
| 104 | + entry: ['src/cli.ts'], |
| 105 | + exe: { |
| 106 | + targets: [ |
| 107 | + { platform: 'linux', arch: 'x64', nodeVersion: '25.7.0' }, |
| 108 | + { platform: 'darwin', arch: 'arm64', nodeVersion: '25.7.0' }, |
| 109 | + { platform: 'win', arch: 'x64', nodeVersion: '25.7.0' }, |
| 110 | + ], |
| 111 | + }, |
| 112 | +}) |
| 113 | +``` |
| 114 | + |
| 115 | +This downloads the target platform's Node.js binary from nodejs.org, caches it locally, and uses it to build the executable. The output files are named with platform and architecture suffixes: |
| 116 | + |
| 117 | +``` |
| 118 | +dist/ |
| 119 | + cli-linux-x64 |
| 120 | + cli-darwin-arm64 |
| 121 | + cli-win-x64.exe |
| 122 | +``` |
| 123 | + |
| 124 | +### Target Options |
| 125 | + |
| 126 | +Each target in the `targets` array accepts: |
| 127 | + |
| 128 | +| Field | Type | Description | |
| 129 | +| ------------- | ------------------------------ | -------------------------------------------------------- | |
| 130 | +| `platform` | `'win' \| 'darwin' \| 'linux'` | Target operating system (aligned with nodejs.org naming) | |
| 131 | +| `arch` | `'x64' \| 'arm64'` | Target CPU architecture | |
| 132 | +| `nodeVersion` | `string` | Node.js version to use (must be `>=25.7.0`) | |
| 133 | + |
| 134 | +:::warning |
| 135 | +When `targets` is specified, the `seaConfig.executable` option is ignored — the downloaded Node.js binary is used instead. |
| 136 | +::: |
| 137 | + |
| 138 | +### Caching |
| 139 | + |
| 140 | +Downloaded Node.js binaries are cached in the system cache directory: |
| 141 | + |
| 142 | +- **macOS:** `~/Library/Caches/tsdown/node/` |
| 143 | +- **Linux:** `~/.cache/tsdown/node/` (or `$XDG_CACHE_HOME/tsdown/node/`) |
| 144 | +- **Windows:** `%LOCALAPPDATA%/tsdown/Caches/node/` |
| 145 | + |
| 146 | +Subsequent builds reuse cached binaries without re-downloading. |
| 147 | + |
| 148 | +## Platform Notes |
| 149 | + |
| 150 | +- On **macOS**, the executable is automatically codesigned (ad-hoc) for Gatekeeper compatibility. When cross-compiling for macOS from a non-macOS host, codesigning will be skipped with a warning. |
| 151 | +- On **Windows**, the `.exe` extension is automatically appended. |
0 commit comments