前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处

简介: 在使用 Deno 构建项目时,生成的可执行文件体积较大,通常接近 100 MB,而 Node.js 构建的项目体积则要小得多。这是由于 Deno 包含了完整的 V8 引擎和运行时,使其能够在目标设备上独立运行,无需额外安装依赖。尽管体积较大,但 Deno 提供了更好的安全性和部署便利性。通过裁剪功能、使用压缩工具等方法,可以优化可执行文件的体积。

在使用 Deno 进行构建时,发现生成的可执行文件体积较大。相比之下,使用 Node.js 构建的项目通常非常小,尤其是在不安装依赖包的情况下,体积通常不到 1MB。然而,Windows 下 Deno 生成的可执行文件体积接近 100 MB,这让我不禁思考:为什么 Deno 打包的产物会如此庞大?是否有可以优化的空间?这种情况让我开始深入研究Deno 的打包方式及其内部结构,希望能够找到一些优化策略或者理解它如此设计的原因。

最后你会发现,这100M包含了所有的资源以及运行时,再也不需要在部署设备安装nodejs或者docker啦

推荐前置阅读: Deno2.0与Bun对比,谁更胜一筹?可能Deno目前更适合serverless业务

Deno 安装

Windows

使用 PowerShell:

irm https://deno.land/install.ps1 | iex

Linux

curl -fsSL https://deno.land/install.sh | sh

更多安装方式请参考 Deno 安装文档

创建项目

  1. 创建一个干净的 📁 目录(可选)。
  2. 在目录中创建一个 test.js 文件。
  3. 编写以下代码,例如:
// 一个简单的应用代码,每隔10秒更新目录下一个文件内的时间戳数据,包含时间读取和文件操作权限
const filePath = `${
     Deno.cwd()}/timestamp`;

async function updateTimestamp() {
   
  while (true) {
   
    const timestamp = new Date().toISOString();
    try {
   
      await Deno.writeTextFile(filePath, timestamp);
      console.log(`Timestamp updated: ${
     timestamp}`);
    } catch (err) {
   
      console.error(`Failed to update timestamp: ${
     err}`);
    }
    await new Promise(resolve => setTimeout(resolve, 10000)); 
  }
}

updateTimestamp();

构建可执行文件

使用 deno compile 命令进行构建:

deno compile --output test ./test.js

在 Windows 下会生成 test.exe

运行可执行文件

方式一:双击执行文件

可以通过双击来运行生成的 test.exe 文件。由于示例代码会持续运行进程,因此可以看到命令窗口。如果是非持续运行的程序,可能只会闪一下。

运行过程中会请求权限:
权限提示

输入 y 允许权限请求后:
在这里插入图片描述
在这里插入图片描述

方式二:命令行授权运行

可以通过命令行一次性授权并运行:

.\test.exe --allow-all

构建物分析

构建物的组成

将生成的 test.exe 文件解压后可以看到它的组成部分:
解压 exe

可以看到两个主要部分:.text (49 MB) 和 .rdata (29 MB),它们占据了可执行文件的大部分空间。

深入分析

Deno 打包后的可执行文件之所以如此庞大,是因为它包含了以下部分:

  1. V8 引擎:Deno 基于 V8 引擎来执行 JavaScript 代码,因此 V8 作为 Deno 运行时的一部分被打包在可执行文件中。
  2. Deno 运行时: Deno 运行时自身也包含了许多功能,如权限管理、模块加载等。这些功能都需要包含在打包的可执行文件中,以确保应用在不同环境中正常运行。

为什么如此设计?

Deno 的设计理念之一是让构建后的可执行文件能够在目标设备上独立运行,无需再额外安装Deno 或其他依赖。这种 "一次构建,到处运行" 的模式使得可执行文件在部署时更加方便,但同时也增加了文件的体积。相比于传统的 Node.js 应用, Deno 将运行时和引擎都集成到可执行文件中,因此文件体积较大。

与 Node.js、Bun 以及 Docker+Node.js 部署的对比

在构建和部署 JavaScript 应用程序时, Deno、Node.js、Bun 以及使用 Docker 打包的 Node.js 应用都有各自的优缺点。下面我们来对比这些不同的工具和方法。

1. Node.js

Node.js 是最广泛使用的 JavaScript 运行时,它依赖于 V8 引擎来执行 JavaScript 代码。使用 Node.js 部署应用程序通常需要先安装 Node.js 环境,然后通过 npm 或 yarn 安装项目的依赖项。Node.js 的优势在于其成熟的生态系统和广泛的社区支持。

然而,Node.js 应用程序部署时需要依赖环境,这意味着必须在目标服务器上安装 Node.js,或者通过容器化的方式来确保环境一致性。此外,Node.js 本身并不直接支持将应用程序打包为单个可执行文件,因此需要其他工具(如 pkg)来实现类似的效果。

2. Bun

Bun 是一种新兴的 JavaScript 运行时,旨在提供比 Node.js 更快的执行速度和更简单的开发体验。Bun 集成了包管理器 📦、JavaScript 运行时和捆绑工具,旨在简化整个开发流程。与 Node.js 相比,Bun 的包管理速度更快,且在性能上进行了优化。

不过,Bun 目前仍在快速发展中,生态系统相对较小,还没有 Node.js 那样广泛的第三方库支持。此外,Bun 的稳定性和兼容性在某些场景下可能还需要进一步验证。

3. Deno

Deno 的主要特点在于安全性和自包含的可执行文件。与 Node.js 不同, Deno 默认禁止网络、文件系统等敏感操作,除非明确授权,这种权限管理的机制使得应用程序更加安全。此外,Deno 可以将应用程序编译为单个自包含的可执行文件,这在部署时非常方便,无需在目标服务器上安装 Deno 运行时。

然而,正因为 Deno 将运行时和 V8 引擎都打包在可执行文件中,导致生成的文件体积非常大。对于一些对文件体积敏感的场景, Deno 的这种设计可能不是最优选择。

4. Docker + Node.js

使用Docker 容器来部署 Node.js 应用是一种非常流行的方法,尤其是在需要环境隔离和一致性的时候。通过 Docker,可以将应用程序及其所有依赖打包在一个容器中,确保在任何支持Docker 的平台上都可以一致地运行。

使用 Docker 部署的优势在于环境的隔离和可移植性,开发者可以确保在本地测试的应用在生产环境中具有相同的依赖和配置。然而,Docker 容器的镜像体积相对较大,这取决于所使用的基础镜像和应用程序的依赖项。此外,使用Docker 还需要一定的运维技能来管理容器的生命周期。

总结对比

  • Node.js:适合需要广泛生态支持的应用,部署时需要环境依赖。
  • Bun:更快的包管理和执行速度,但生态系统还不成熟。
  • Deno:提供安全性和自包含的可执行文件,部署简单,但文件体积较大。
  • Docker + Node.js:提供环境一致性和隔离,适合复杂的生产环境,但镜像体积较大。

根据具体的应用场景和需求,开发者可以选择最适合的工具和方法来进行部署。

可优化的方向

虽然Deno 的可执行文件包含了完整的运行时和引擎,使其体积庞大,但我们可以考虑以下优化方向:

  1. 裁剪功能:如果应用不需要某些运行时功能,可以探索是否有办法裁剪掉不必要的部分,减少最终可执行文件的体积。
  2. 压缩工具:使用压缩工具如 UPX 对生成的可执行文件进行压缩,可以有效减小文件体积。
  3. 模块化设计:在开发时尽可能减少使用第三方库和不必要的模块,保持代码精简,从源头上控制构建物的大小。

结论

Deno 打包的可执行文件体积较大是其设计使然,目的是为了在不同环境中实现独立运行和无依赖的便利性。虽然它的文件体积相比传统 Node.js 应用较大,但可以通过裁剪功能、压缩工具等方式进行一定程度的优化,以适应不同的应用场景需求。

构建成可执行文件后,你的后端应用就可以在没有运行时的设备允许了,尤其是ecs、轻量应用服务器,实现一键部署~

相关文章
|
1天前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
2天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
2天前
|
前端开发 应用服务中间件 nginx
docker安装nginx,前端项目运行
通过上述步骤,你可以轻松地在Docker中部署Nginx并运行前端项目。这种方法不仅简化了部署流程,还确保了环境的一致性,提高了开发和运维的效率。确保按步骤操作,并根据项目的具体需求进行相应的配置调整。
37 25
|
3天前
|
Dart 前端开发 架构师
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
|
19天前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
142 18
|
2月前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
227 8
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
|
2月前
|
JavaScript 前端开发 安全
2024年前端开发新趋势:TypeScript、Deno与性能优化
2024年前端开发迎来新趋势:TypeScript 5.0引入装饰器正式支持、const类型参数及枚举改进;Deno 1.42版推出JSR包注册表、增强Node.js兼容性并优化性能;性能优化策略涵盖代码分割、懒加载及现代构建工具的应用。这些变化推动前端开发向更高效率和安全性发展。
|
3月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
255 14
|
3月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
69 0
|
3月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。

热门文章

最新文章