跳到主要内容
Use deno compile to create cross platform single executable binaries.

使用 Deno Compile 创建自包含可执行程序

Deno v1.6 版本以来,deno compile 命令使开发者能够将 JavaScript 和 TypeScript 程序转换为可在所有主流平台上运行的独立二进制文件——无需依赖项,无需额外安装。这具有重大意义

  • 跨平台兼容性:分发一个无需 Deno 运行时或依赖项即可工作的单个二进制文件。
  • 打包资源:将你的应用程序所需的一切都打包到二进制文件中,以便于移植。
  • 简化的部署:将一个二进制文件发布到生产环境,减少复杂性。
  • 改进的启动时间:与典型的服务器或运行时设置相比,启动速度更快。

Deno 2 以来,我们为 deno compile 引入了更多改进,例如 支持 npm 包Web Workers交叉编译更小的二进制文件大小以及使用自定义图标的代码签名。 这些升级意味着你现在不仅可以编译脚本,还可以将完整的应用程序(如桌面游戏)直接编译为原生二进制文件。

在本文中,我们将探讨 deno compile 的独特之处、其工作原理,以及不同用例的示例,这些示例突显了它相对于生态系统中其他替代方案的优势。

🚨️ Deno 2 发布了。 🚨️

凭借与 Node/npm 的向后兼容性内置包管理一体化零配置工具链以及原生 TypeScriptWeb API 支持,编写 JavaScript 从未如此简单。

什么是 deno compile

Deno 为 JavaScript 和 TypeScript 提供零配置工具链,因此你无需在编写任何代码之前拼凑不同的工具。deno compile 是一个子命令,可让你从 JavaScript 或 TypeScript 代码构建单个二进制文件。与 Node 的 8 步编译过程不同,deno compile 仅需一个命令。

此子命令允许你跳过安装要求,并在未安装 Deno 的系统上运行二进制文件,跨越 Windows、macOS 和 Linux 等平台。Deno 编译的二进制文件也针对大小进行了优化。如果你来自 Node,这种简洁性减少了在环境之间移动代码时的摩擦,尤其是在为不同的操作系统目标进行交叉编译时。

deno compile 的工作原理

虽然它被称为“compile”,但 deno compile 并非以传统意义上的方式编译 JavaScript。相反,它将你的 JavaScript 和 TypeScript 代码嵌入到一个特殊的 Deno 运行时二进制文件中,称为 denort(“Deno runtime”的缩写)。

以下是执行 deno compile 时过程的概要:

  1. 下载精简版的运行时 denort。 如果你正在为不同的操作系统进行交叉编译,则会下载该平台的 denort
  2. 你的脚本以及任何依赖项都会捆绑到一个 eszip 文件中,这是一种用于序列化 ECMAScript 模块图的无损格式。
  3. 该捆绑包使用 Sui 注入到 denort 二进制文件中。

通过将捆绑包嵌入到可执行文件的某个部分,输出的二进制文件仍然可以进行代码签名。

示例

基本的自包含二进制文件

首先,让我们看看从 TypeScript 脚本创建一个单独的可执行文件是多么容易。

// main.ts
import open from "jsr:@rdsq/open";

await open("https://www.youtube.com/watch?v=dQw4w9WgXcQ");

编译它非常简单,只需:

deno compile -A -o runme main.ts

这会输出一个可执行的二进制文件 (runme),其中包含所有必需的依赖项。现在你可以在任何平台上共享此单个文件,而无需最终用户安装 Deno。

请注意,你可以在 deno compile 命令中传递选择性加入的权限标志,例如 --allow-net。权限标志将保留在编译后的二进制文件中,从而为你的二进制文件的使用方式提供额外的安全层。

为 Windows 交叉编译

假设你想与 Windows 用户共享该应用程序。使用 --target 标志,你可以为其交叉编译 Windows 版本

deno compile --allow-all -o runme --target x86_64-pc-windows-msvc main.ts

现在你有了 runme.exe,一个与 Windows 兼容的二进制文件。你甚至可以使用 --icon 标志添加自定义图标,以获得更精致的外观

deno compile --allow-all -o runme --target x86_64-pc-windows-msvc --icon icon.ico main.ts

代码签名

代码签名确保你的二进制文件经过验证且值得信赖,这对于软件分发至关重要。Deno 简化了这一点,即使在 macOS 上,你也可以像使用任何其他应用程序一样使用 codesign

让我们确认我们二进制文件的完整性

codesign --verify -vv ./runme
./runme: valid on disk
./runme: satisfies its Designated Requirement

我们编译的二进制文件已正确代码签名,可以发布了。

编译 NPM 包

当然,可以使用 deno compile 编译 NPM 包。这种方法非常适合对性能敏感的 CI 环境,或者当你需要工具的单个便携版本时。

例如,让我们在 npm 本身使用 deno compile

deno compile -A npm:npm

运行编译后的 npm 二进制文件很简单,甚至显示出性能提升。在测试中,Deno 编译的 npm 二进制文件比常规 npm 快约 1.9 倍

# hyperfine "./npm -v" "npm -v"
Benchmark 1: ./npm -v
  Time (mean ± σ):      40.1 ms ±  2.0 ms    [User: 37.7 ms, System: 5.3 ms]
  Range (min … max):    38.9 ms … 51.8 ms    71 runs

Benchmark 2: npm -v
  Time (mean ± σ):      75.2 ms ±  7.6 ms    [User: 59.1 ms, System: 9.0 ms]
  Range (min … max):    69.2 ms … 105.0 ms   40 runs

Summary
  ./npm -v ran
    1.87 ± 0.21 times faster than npm -v

这种方法也适用于其他流行的 npm 工具,如 prettiereslint,为你提供更快、更便携的版本。

游戏和桌面应用

deno compile 还开启了将基于 Web 的游戏和应用程序捆绑为原生桌面可执行文件的潜力。例如,你可以将一个 HTML/CSS/JavaScript 游戏转换为一个二进制文件,该文件易于共享并在任何桌面上启动。

观看使用 deno compile 捆绑 HTML 游戏的视频演示。

看看这个 Flappybird 克隆版,它可以使用 Deno 编译成桌面应用程序

deno compile --unstable-ffi --env -o flappybird -A main.js

捆绑资源

虽然 deno compile 目前尚不支持直接捆绑资源(尚未!),但可以将 .png 或其他资源文件转换为 base64 编码的 .js 文件,并将 它们导入到你的项目中,从而将它们包含在最终的二进制文件中。 这种方法虽然是一种变通方法,但使开发人员能够将游戏和其他资源打包在单个可执行文件中。

未来展望

我们正在根据你的反馈不断改进 deno compile,未来的更新将简化资源捆绑、支持更多框架(如 Svelte)、减小二进制文件大小,并通过缓存进一步缩短启动时间。

🚨️ 想了解更多关于 Deno 的信息吗? 🚨️

查看我们全新的 Learn Deno 教程系列,你将在其中学习:

……以及更多内容,都在简短的视频中。新的教程每周二和周四发布。