On this page
deno compile
标志 Jump to heading
与 deno install 一样,执行脚本时使用的运行时标志必须在编译时指定。这包括权限标志。
deno compile --allow-read --allow-net jsr:@std/http/file-server
脚本参数 可以部分嵌入。
deno compile --allow-read --allow-net jsr:@std/http/file-server -p 8080
./file_server --help
框架检测 Jump to heading
从 Deno 2.8 开始,deno compile .(或 deno compile <directory>)会检测常见的 Web 框架,并生成一个知道如何启动它们的入口点。检测到的构建脚本会先运行,因此编译后的二进制文件始终包含最新构建。
支持的框架:
- Next.js
- Astro
- Fresh (1.x 和 2.x)
- Remix
- SvelteKit
- Nuxt
- SolidStart
- TanStack Start
- Vite (SSR, plus SPA/MPA projects served as static output)
# 在 Next.js / Astro / Fresh / 等项目中
deno compile .
# 或指向某个特定应用目录
deno compile ./apps/web
生成的入口点使用 import.meta.dirname,因此框架资源路径可以在编译后的二进制文件内部,正确地相对于 虚拟文件系统 解析。
如果项目不匹配任何受支持的框架,deno compile 将报错退出。
监听模式 Jump to heading
传递 --watch 可在编译图中的文件发生变化时重新构建可执行文件:
deno compile --watch main.ts
使用 --watch-exclude 可防止特定路径触发重建,并使用
--no-clear-screen 可在两次重建之间保留终端输出:
deno compile --watch --watch-exclude=./dist --no-clear-screen main.ts
交叉编译 Jump to heading
您可以使用 --target 标志为其他平台进行交叉编译二进制文件。
# 为 Apple Silicon 进行交叉编译
deno compile --target aarch64-apple-darwin main.ts
# 为 Windows 进行交叉编译并添加图标
deno compile --target x86_64-pc-windows-msvc --icon ./icon.ico main.ts
支持的目标 Jump to heading
Deno 支持针对所有目标的交叉编译,而不管主机平台。
| 操作系统 | 架构 | 目标 |
|---|---|---|
| Windows | x86_64 | x86_64-pc-windows-msvc |
| macOS | x86_64 | x86_64-apple-darwin |
| macOS | ARM64 | aarch64-apple-darwin |
| Linux | x86_64 | x86_64-unknown-linux-gnu |
| Linux | ARM64 | aarch64-unknown-linux-gnu |
denort 二进制文件 Jump to heading
deno compile 将您的程序嵌入到 denort(“Deno 运行时”)中:这是一个精简版的 Deno 构建,仅包含运行已编译程序所需的内容,不包含任何工具子命令。使用 denort 作为基础而不是完整的 deno 二进制文件,是编译后的可执行文件更小的原因。
第一次为某个给定的 Deno 版本和目标进行编译时,Deno 会从 dl.deno.land 下载匹配的 denort-<target>.zip 并将其缓存到 DENO_DIR 中。这也是交叉编译的工作方式:使用 --target 编译会获取该平台的 denort。后续的编译会复用缓存的二进制文件,并且可以离线运行。
要使用自定义的或本地构建的运行时作为基础,请将 DENORT_BIN 环境变量设置为其路径。Deno 也会自动识别放在 deno 可执行文件旁边的 denort 二进制文件。
图标 Jump to heading
可以通过在目标为 Windows 时使用 --icon 标志来为可执行文件添加图标。图标必须为 .ico 格式。
deno compile --icon icon.ico main.ts
# 带有图标的交叉编译
deno compile --target x86_64-pc-windows-msvc --icon ./icon.ico main.ts
动态导入 Jump to heading
默认情况下,可静态分析的动态导入(在 import("...") 调用表达式中包含字符串字面量的导入)会被包含在输出中。
// calculator.ts 及其依赖将包含在二进制文件中
const calculator = await import("./calculator.ts");
但不可静态分析的动态导入则不会:
const specifier = condition ? "./calc.ts" : "./better_calc.ts";
const calculator = await import(specifier);
要包含不可静态分析的动态导入,请指定 --include <path> 标志。
deno compile --include calc.ts --include better_calc.ts main.ts
包含数据文件或目录 Jump to heading
从 Deno 2.1 开始,您可以通过 --include <path> 标志在可执行文件中包含文件或目录。
deno compile --include names.csv --include data main.ts
然后通过 import.meta.dirname 相对于当前模块的目录路径读取文件:
// main.ts
const names = Deno.readTextFileSync(import.meta.dirname + "/names.csv");
const dataFiles = Deno.readDirSync(import.meta.dirname + "/data");
// 在这里使用 names 和 dataFiles
请注意,这目前仅适用于文件系统上的文件,不适用于远程文件。
--include 会将嵌入的 .js 和 .ts 文件视为模块图的根,因此会解析并转译它们。若要按原样嵌入文件,而不进行任何模块解析,请改用 --include-as-is。对于已处理过、并且作为 Deno 模块会解析失败的预构建前端打包产物(例如 Vite 或 webpack 输出),这是正确的选择:
deno compile --include-as-is ./dist main.ts
在 deno.json 中配置 include / exclude Jump to heading
可以在 deno.json 中以声明式方式设置 --include 和 --exclude 路径,这样您就不必在每次调用 deno compile 时重复指定它们:
{
"compile": {
"include": ["names.csv", "data", "worker.ts"],
"exclude": ["data/secrets", "**/*.test.ts"]
}
}
CLI 标志会与配置合并:--include 和 --exclude 会追加到 deno.json 中的列表,而不是替换它们。更多详情请参阅配置指南中的 Compile config 部分,包括如何在同一块中声明 permissions。
Worker Jump to heading
与不可静态分析的动态导入类似,默认情况下,[worker](../web_platform_apis/#web-workers) 的代码不会包含在编译后的可执行文件中。有两种方法可以包含 worker:
- 使用
--include <path>标志包含 worker 代码。
deno compile --include worker.ts main.ts
- 使用可静态分析的导入导入 worker 模块。
// main.ts
import "./worker.ts";
deno compile main.ts
打包依赖 Jump to heading
默认情况下,deno compile 会将解析后的整个 node_modules 树嵌入到
可执行文件中。对于包含大量 npm 依赖的项目,这可能会使二进制文件变大
并且启动变慢。--bundle 标志会先通过打包器处理您的入口文件,然后再嵌入,
因此最终进入二进制文件的只会是程序实际用到的代码。
deno compile --bundle main.ts
对于纯 ESM 依赖树,树摇会移除所有未使用内容,npm 负载会被完全丢弃,从而生成一个小得多的二进制文件。当命中 CommonJS 包或原生插件(.node)时,相关包会被嵌入,以便它们在运行时仍可工作,但未命中的包仍会被排除。
--bundle 可以自动识别若干真实世界中的模式:
- CommonJS 和原生插件 — 会检测 CJS 依赖和
.node原生插件,并嵌入提供它们的包。 - Workers — 会发现
new Worker(new URL("./worker.ts", import.meta.url), ...)调用,每个 worker 都会单独打包并与主包一起嵌入。 package.json读取 — 在运行时读取自身package.json的包(例如为了报告版本号)会自动包含该文件。
压缩打包结果 Jump to heading
将 --bundle 与 --minify 结合使用,可以压缩打包后的输出。这会同时减小嵌入包的大小和运行时内存使用,但代价是堆栈跟踪可读性降低。
deno compile --bundle --minify main.ts
--minify 只有与 --bundle 结合使用时才有意义。
限制 Jump to heading
由于打包依赖于对代码进行静态分析,无法追踪的模式会从二进制文件中移除:
- 对不是字符串字面量的标识符执行动态
require()/import()。 - 使用计算得到的 URL 启动的 workers,或从传递依赖而不是您自己的源代码中启动的 workers。
如果您的程序依赖这些内容,请将其保持为可静态分析,使用 --include 添加所需文件,或者在不使用 --bundle 的情况下编译。
Self-Extracting Executables Jump to heading
By default, compiled executables serve embedded files through a virtual file system in memory. The --self-extracting flag changes this behavior so that the binary extracts all embedded files to disk on first run and uses real file system operations at runtime.
deno compile --self-extracting main.ts
This is very useful in scenarios where code needs real files on disk, such as native plugins or native code that reads relative files.
The extraction directory is chosen in order of priority:
<exe_dir>/.<exe_name>/<hash>/(adjacent to the compiled binary)- Platform data directory fallback:
- Linux:
$XDG_DATA_HOME/<exe_name>/<hash>or~/.local/share/<exe_name>/<hash> - macOS:
~/Library/Application Support/<exe_name>/<hash> - Windows:
%LOCALAPPDATA%\<exe_name>\<hash>
- Linux:
Files are extracted only once — subsequent runs reuse the directory if it already exists and the hash matches.
Trade-offs Jump to heading
Self-extracting mode provides broader compatibility, but there are some trade-offs:
- Initial startup cost: The first run takes longer because files must be extracted.
- Disk usage: Extracted files take up additional disk space.
- Memory usage: Memory usage is higher because embedded contents can no longer be referenced as static data.
- Tampering risk: Users or other code may modify the extracted files on disk.
代码签名 Jump to heading
macOS Jump to heading
默认情况下,在 macOS 上,编译后的可执行文件将使用临时签名进行签名,等同于运行 codesign -s -:
deno compile -o main main.ts
codesign --verify -vv ./main
./main: 磁盘上的有效
./main: 满足其指定要求
您可以在对可执行文件进行代码签名时指定签名身份,就像您对任何其他 macOS 可执行文件所做的那样:
codesign -s "Developer ID Application: Your Name" ./main
有关 macOS 上代码签名和公证的更多信息,请参考 官方文档。
Windows Jump to heading
在 Windows 上,可以使用 SignTool.exe 工具对编译后的可执行文件进行签名。
deno compile -o main.exe main.ts
signtool sign /fd SHA256 main.exe
可执行文件中的持久化存储 Jump to heading
编译后的二进制文件会被视为一个独立应用,因此基于源的
存储会在平台的应用数据目录中跨运行持久化
(Windows 上为 %LOCALAPPDATA%,macOS 上为 ~/Library/Application Support,
Linux 上为 $XDG_DATA_HOME):
localStorage和 Web Cache API 会在该目录中读写。- 不带路径调用的
Deno.openKv()会在此处打开一个 持久化数据库,而不是回退到内存数据库。
每个编译后的应用都会根据其标识获得自己的位置,因此不同应用不会共享存储。
这个标识来自 --app-name 标志,它会在编译时被写入,并在未指定时回退到输出文件名:
deno compile --app-name my-app main.ts
由于决定目录的是名称(而不是模块路径),因此即使你重命名二进制文件,存储也会
在多次运行之间保持稳定;使用相同 --app-name 构建的两个二进制文件会共享同一个存储,
而不同名称的应用则彼此隔离。使用不同的 --app-name 重新编译会启动一个全新的存储。
deno compile [OPTIONS] [SCRIPT_ARG]...Compiles the given script into a self contained executable.
deno compile --allow-read --allow-net jsr:@std/http/file-server
deno compile --output file_server jsr:@std/http/file-server
Any flags specified which affect runtime behavior will be applied to the resulting binary.
This allows distribution of a Deno application to systems that do not have Deno installed. Under the hood, it bundles a slimmed down version of the Deno runtime along with your JavaScript or TypeScript code.
Cross-compiling to different target architectures is supported using the --target flag.
On the first invocation of deno compile, Deno will download the relevant binary and cache it in $DENO_DIR.
Type checking options Jump to heading
--check<CHECK_TYPE>optionalSet type-checking behavior. This subcommand type-checks local modules by default, so passing --check is redundant; pass --check=all to also type-check remote modules. Alternatively, use the 'deno check' subcommand.
--no-check<NO_CHECK_TYPE>optionalSkip type-checking. If the value of "remote" is supplied, diagnostic errors from remote modules will be ignored.
Dependency management options Jump to heading
--cached-onlyRequire that remote dependencies are already cached.
--frozen<BOOLEAN>optionalError out if lockfile is out of date.
Load import map file from local file or remote URL.
--lock<FILE>optionalCheck the specified lock file. (If value is not provided, defaults to "./deno.lock").
--no-lockDisable auto discovery of the lock file.
--no-npmDo not resolve npm modules.
--no-remoteDo not resolve remote modules.
--node-modules-dir<MODE>optionalSelects the node_modules directory mode for npm packages (not a path). One of: auto (create a local node_modules directory and install npm packages into it), manual (use the existing local node_modules directory, do not modify it), none (do not use a local node_modules directory; resolve npm packages from the global cache). Defaults to auto when the flag is passed without a value.
--node-modules-linker<MODE>Sets the linker mode for npm packages (isolated or hoisted).
--reload, -r<CACHE_BLOCKLIST>optionalReload source code cache (recompile TypeScript). With no value, reloads everything. Pass a comma-separated list of specifiers to reload only those modules; npm: reloads all npm modules; npm:chalk reloads a single npm module; jsr:@std/http/file-server,jsr:@std/assert/assert-equals reloads specific modules.
--vendor<vendor>optionalToggles local vendor folder usage for remote modules and a node_modules folder for npm packages.
Options Jump to heading
--allow-scripts<PACKAGE>optionalAllow running npm lifecycle scripts for the given packages
Note: Scripts will only be executed when using a node_modules directory (--node-modules-dir).
--cert<FILE>Load certificate authority from PEM encoded file.
--conditions<conditions>Use this argument to specify custom conditions for npm package exports. You can also use DENO_CONDITIONS env var. .
Configure different aspects of deno including TypeScript, linting, and code formatting.
Typically the configuration file will be called deno.json or deno.jsonc and
automatically detected; in that case this flag is not necessary.
--env-file<FILE>optionalLoad environment variables from local file Only the first environment variable with a given key is used. Existing process environment variables are not overwritten, so if variables with the same names already exist in the environment, their values will be preserved. Where multiple declarations for the same environment variable exist in your .env file, the first one encountered is applied. This is determined by the order of the files you pass as arguments.
--ext<ext>Set content type of the supplied file.
--location<HREF>Value of globalThis.location used by some web APIs.
--minimum-dependency-age<minimum-dependency-age>(Unstable) The age in minutes, ISO-8601 duration or RFC3339 absolute timestamp (e.g. '120' for two hours, 'P2D' for two days, '2025-09-16' for cutoff date, '2025-09-16T12:00:00+00:00' for cutoff time, '0' to disable).
--no-code-cacheDisable V8 code cache feature.
--no-configDisable automatic loading of the configuration file.
--preload<FILE>A list of files that will be executed before the main module.
--require<FILE>A list of CommonJS modules that will be executed before the main module.
--seed<NUMBER>Set the random number generator seed.
--v8-flags<V8_FLAGS>optionalTo see a list of all available flags use --v8-flags=--help
Flags can also be set via the DENO_V8_FLAGS environment variable.
Any flags set with this flag are appended after the DENO_V8_FLAGS environment variable.
Compile options Jump to heading
--app-name<app-name>Stable identity for the compiled app.
Determines where origin-bound storage such as the default Deno.openKv(),
localStorage and caches is persisted (under the platform's app data directory).
Defaults to the output file name. Set this to keep storage stable across renames.
--bundleExperimental. Bundle the entrypoint with esbuild before embedding, instead of shipping the whole node_modules tree. Produces a smaller binary with faster startup, at the cost of dropping dynamic require/import patterns that can't be statically traced.
--exclude<exclude>Excludes a file/directory in the compiled executable. Use this flag to exclude a specific file or directory within the included files. For example, to exclude a certain folder in the bundled node_modules directory.
--exclude-unused-npmEmbed only the npm packages reachable from the module graph (managed npm; no node_modules directory).
Without this flag the full managed npm snapshot from the lockfile / package.json is embedded.
Reduces binary size when the lockfile contains packages the entrypoint does not import.
Skips packages that are only reached through non-statically-analyzable dynamic imports;
pass those with --include npm:
--icon<icon>Set the icon of the executable on Windows (.ico).
--include<include>Includes an additional module or file/directory in the compiled executable. Use this flag if a dynamically imported module or a web worker main module fails to load in the executable or to embed a file or directory in the executable. This flag can be passed multiple times, to include multiple additional modules.
--minifyExperimental. Minify the bundled output. Only meaningful with --bundle.
Reduces both the embedded bundle size and runtime memory use, at the cost of less readable stack traces.
--no-terminalHide terminal on Windows.
--output, -o<output>Output file (defaults to $PWD/
--self-extractingCreate a self-extracting binary that extracts the embedded file system to disk on first run and then runs from there.
--target<target>Target OS architecture.
File watching options Jump to heading
--no-clear-screenDo not clear terminal screen when under watch mode.
--watchWatch for file changes and restart process automatically. Only local files from entry point module graph are watched.
--watch-exclude<FILES>optionalExclude provided files/patterns from watch mode.