使用 Deno Compile 构建自包含可执行程序
自 Deno v1.6 发布以来,deno compile
命令使开发者能够将 JavaScript 和 TypeScript 程序转换为可在所有主流平台上运行的独立单一二进制文件——无需依赖,无需额外安装。这带来了重大意义
- 跨平台兼容性:分发一个单一的二进制文件,无需 Deno 运行时或依赖即可运行。
- 捆绑资源:将应用程序所需的一切打包到二进制文件中,方便移植。
- 简化部署:将一个二进制文件部署到生产环境,降低复杂性。
- 改进启动时间:与典型的服务器或运行时设置相比,启动时间更快。
自 Deno 2 发布以来,我们对 deno compile
进行了更多改进,例如支持 npm 包、Web Worker、交叉编译、更小的二进制文件大小以及支持自定义图标的代码签名。这些升级意味着您现在不仅可以编译脚本,还可以将桌面游戏等完整应用程序直接编译成本机二进制文件。
在这篇文章中,我们将探讨 deno compile
的独特之处、其工作原理以及突出其相对于生态系统中其他替代方案优势的不同用例示例。
🚨️ Deno 2 已发布。 🚨️
凭借与 Node/npm 的向后兼容性、内置包管理、一体化零配置工具链以及原生 TypeScript 和Web API 支持,编写 JavaScript 从未如此简单。
deno compile
?
什么是 Deno 提供一个零配置的 JavaScript 和 TypeScript 工具链,因此您无需在编写任何一行代码之前拼凑不同的工具。其中一个子命令是 deno compile
,它允许您从 JavaScript 或 TypeScript 代码构建单个二进制文件。与 Node 的8 步编译过程不同,deno compile
只需要一个命令。
这个子命令让您可以跳过安装要求,在未安装 Deno 的系统上运行二进制文件,支持 Windows、macOS 和 Linux 等平台。Deno 编译的二进制文件也针对大小进行了优化。如果您是从 Node 迁移过来的,这种简洁性在不同环境之间移动代码时减少了摩擦,尤其是在为不同操作系统目标进行交叉编译时。
deno compile
的工作原理
尽管称为“编译”,但 deno compile
并非传统意义上的 JavaScript 编译。相反,它将您的 JavaScript 和 TypeScript 代码嵌入到一个特殊的 Deno 运行时二进制文件中,该文件名为 denort
(“Deno 运行时”的缩写)。
以下是执行 deno compile
时过程的高级概述
- 精简版的运行时
denort
会被下载。如果您正在为不同的操作系统进行交叉编译,则会下载该平台的denort
。 - 您的脚本以及所有依赖项被捆绑到一个
eszip
文件中,这是一种用于序列化 ECMAScript 模块图的无损格式。 - 该捆绑包使用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 工具,如 prettier
和 eslint
,为您提供更快、更便携的版本。
游戏和桌面应用程序
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 吗? 🚨️
查看我们新的Deno 学习教程系列,您将在其中学习
……以及更多内容,以简短、易于理解的视频形式呈现。新教程每周二和周四发布。