# 编译为单文件可执行程序

`deno compile` 把入口模块图与精简运行时 `denort` 打成一个自包含可执行文件，目标机器不需要安装 Deno。

## 基本用法

```bash
deno compile --output=server main.ts
./server
```

产物是一个与平台绑定的二进制文件。运行时参数必须在编译时声明，包括权限：

```bash
deno compile --allow-net --allow-env=PORT --output=server main.ts
```

<Callout type="warn" title="权限在编译时固化">
编译后的二进制不接受 `--allow-*` 等运行时标志。权限范围在 `deno compile` 时确定并写入产物，事后无法收紧或放宽；按最小权限编译，不要把 `-A` 烧进要分发的文件。
</Callout>

## 交叉编译

`--target` 可从任意主机平台交叉编译。当前支持五个目标三元组：

| 目标 | 平台 |
| --- | --- |
| `x86_64-pc-windows-msvc` | Windows x86_64 |
| `x86_64-apple-darwin` | macOS x86_64 |
| `aarch64-apple-darwin` | macOS ARM64 |
| `x86_64-unknown-linux-gnu` | Linux x86_64 |
| `aarch64-unknown-linux-gnu` | Linux ARM64 |

```bash
deno compile --target=aarch64-unknown-linux-gnu --output=server-linux-arm64 main.ts
```

对应目标的 `denort` 会下载到 `DENO_DIR` 缓存。交叉产物必须在目标平台真实启动一次，不要只验证“编译通过”。

## 嵌入资源

自 Deno 2.1 起，`--include` 可把文件或目录嵌进二进制，并通过 `import.meta` 相对路径读取：

```bash
deno compile --include=./data --include=worker.ts main.ts
```

```ts
const csv = await Deno.readTextFile(import.meta.dirname + "/data/names.csv");
```

- `--include` 可多次传入；只支持本地文件，远程模块无法嵌入。
- 被嵌入的 `.js` / `.ts` 会作为模块图根参与解析；预构建的前端产物用 `--include-as-is` 原样嵌入，避免被再次转译。
- `deno.json` 的 `compile` 块可声明 `include` / `exclude` 数组，与 CLI 标志合并。
- 默认嵌入整个已解析的 `node_modules`；实验性的 `--exclude-unused-npm` 只嵌入可达的 npm 包。

## 与 Docker / Deploy 的边界

| 场景 | 优先方案 |
| --- | --- |
| 分发 CLI 工具、单文件后台程序 | `deno compile` |
| 服务需要系统库、CA、shell 或多个进程协作 | [Docker 与容器](/docs/deploy/docker) |
| HTTP 服务需要托管 TLS、多区域部署与自动扩缩 | [Deno Deploy](/docs/deploy/deno-deploy) |

`deno compile` 解决“分发形态”，不解决进程管理、滚动升级或证书。服务长期运行仍需要 systemd、容器编排或托管平台。

## 已知局限

- 动态导入只有字符串字面量会被静态纳入；计算出的 specifier 需要 `--include` 显式带上。
- Worker 代码默认不进产物，用 `--include` 或静态 `import "./worker.ts"` 引入。
- 原生插件（FFI、`.node` 加载项）依赖自解压模式，首次运行更慢且占用额外磁盘；按目标平台逐一验证。
- 二进制与 Deno 版本绑定，运行时升级需要重新编译分发。

官方参考：[deno compile](https://docs.deno.com/runtime/reference/cli/compile/)。
