9 月 8 日,JavaScript 社区出现了新的动态:Bun v1.0。或许大家都想知道:Bun的本质是什么?为什么每个人都将其与久经考验的Node.js相提并论?Bun只是另一种稍纵即逝的趋势,还是要重新定义游戏?让我们深入研究,并了解 Bun 与 Node 相比到底如何。
什么是 Bun.js?
Bun 是一款适用于 JavaScript 和 TypeScript 应用程序的超快速一体化工具包。Bun 的美妙之处在于它能够简化开发流程,使其比以往更加顺畅和高效。这是可能的,因为 Bun 不仅仅是一个运行时,它还是一个包管理器、一个捆绑器和一个测试运行器。
Bun 解决了什么问题?
Node.js 于 2009 年诞生,具有开创性。然而,与许多技术一样,随着技术的发展,其复杂性也随之增加。把它想象成一座城市。随着城市的扩张,交通拥堵可能会成为一个问题。
Bun 的目标是成为缓解这种拥堵的新基础设施,让一切运行得更顺畅、更快。这不是重新发明轮子,而是对其进行改进,确保在我们获得速度和简单性的同时,我们不会失去 JavaScript 独特和强大的本质。
Bun 被设计为 Node.js 的更快、更精简、更现代的替代品,所以让我们仔细看看一些比较。但首先让我们讨论另一个话题。
Bun 与 Node.js 与 Deno
在讨论 JavaScript 运行时的演变时,很难忽视Deno。Node.js 的创建者 Ryan Dahl 推出了 Deno 作为一个新的运行时,旨在解决他在 Node.js 中发现的一些挑战和遗憾。
Deno 是 JavaScript 和 TypeScript 的安全运行时。它直接解决了 Node.js 的许多缺点。例如,Deno 原生支持 TypeScript,无需外部工具。与 Node.js 不同,Node.js 的脚本默认具有广泛的权限,Deno 采用安全第一的方法,要求开发人员显式授予潜在敏感操作的权限,例如文件系统访问或网络连接。
虽然 Deno 提供了 Node.js 的一个引人注目的替代方案,但它还没有达到 Node.js 的广泛采用程度。
JavaScript 引擎对比
JavaScript 引擎是一种将我们编写的 JavaScript 代码转换为机器代码的程序,使计算机能够执行特定的任务。
Node.js 使用为 Chrome 浏览器提供支持的 Google V8 引擎,而 Bun 使用JavaScriptCore (JSC),这是 Apple 为 Safari 开发的开源 JavaScript 引擎。
V8和JSC有不同的架构和优化策略。JSC 优先考虑更快的启动时间和减少内存使用以及稍慢的执行时间。另一方面,V8 优先考虑快速执行,并进行更多运行时优化,这可能会导致更多内存使用。
bun 的运行速度比 deno 快 2.19 倍,比 Node 快 4.81 倍
JavaScript转译
虽然 Node.js 是一个强大的 JavaScript 运行时,但它本身并不支持 TypeScript 文件。要在 Node.js 环境中执行 TypeScript,需要外部依赖项 ts-node 使用构建步骤将 TypeScript (TS) 转换为 JavaScript (JS),然后运行生成的 JS 代码。
Bun 提供了一种更精简的方法。它带有集成到运行时的 JavaScript 转译器。这允许您直接运行。js, .ts, .jsx 和.tsx文件。Bun 的内置转译器将这些文件无缝转换为普通 JavaScript,无需额外步骤即可立即执行。
运行 TypeScript 文件时,速度差异会被放大,因为 Node.js 在运行之前需要一个转译步骤。
ESM和CommonJS兼容性
模块系统允许开发人员将代码组织成可重用的段。在 JavaScript 中,两个主要的模块系统是CommonJS和ES 模块(ESM)。CommonJS 源自 Node.js,使用require和module.exports进行同步模块处理,非常适合服务器端操作。
ES6 中引入的 ESM 采用了import和export语句,提供了一种更加静态和异步的方法,针对浏览器和现代构建工具进行了优化。
// CommonJS in Node.js (index.js)
const colors = require("colors");
console.log(colors.green('Hello, world!'));
对于 Node.js 中的 ES 模块,您有以下两个选项之一:
- 您需要包含
"type": "module"在您的package.json. - 使用
.mjs扩展名。
// ESM in Node.js (index.mjs)
import chalk from 'chalk';
console.log(chalk.blue('Hello, world!'));
从 CommonJS 到 ES 模块 (ESM) 的过渡是一个复杂的过程。在 ESM 推出后,Node.js 花了五年时间才在没有实验标志的情况下支持它。尽管如此CommonJS 在生态系统中仍然很流行。
Bun 通过支持两者而无需任何特殊配置,从而简化了模块系统。Bun 的突出特点是它能够在同一个文件中同时支持import和require(),这在 Node.js 中是不可能实现的:
// Mixed modules in Bun (index.js)
import chalk from "chalk";
const colors = require("colors");
console.log(chalk.magenta('Hello from chalk!'));
console.log(colors.cyan('Hello from colors!'));
热重载
热重载是一项功能,可在代码更改时自动刷新或实时重新加载应用程序的某些部分,从而提高开发人员的工作效率,而无需完全重新启动。
在 Node.js 生态系统中,您有多种选择来实现热重载。一种流行的工具是nodemon,它可以硬重启整个过程:
nodemon index.js 或者,从 Node.js v18 开始,引入了一个实验性--watch标志
node --watch index.js
这两种方法的目的都是在代码更改时提供应用程序的实时重新加载。然而,他们可能有不同的行为,特别是在某些环境或场景下。
例如,nodemon可能会导致中断,例如断开 HTTP 和 WebSocket 连接,而该--watch标志处于实验阶段,可能无法提供全套功能,并且在 GitHub issues中报告了一些问题。
Bun 将热重载更进一步。通过使用该标志运行 Bun --hot,可以启用热重载bun --hot index.ts
与可能需要重新启动整个进程的 Node.js 方法不同,Bun 会就地重新加载代码,而不会终止旧进程。这可确保 HTTP 和 WebSocket 连接保持不间断,并保留应用程序状态,从而提供更流畅的开发体验。
Node.js 兼容性
当过渡到新的运行时或环境时,兼容性通常是开发人员最关心的问题。Bun 通过将自己定位为 Node.js 的直接替代品来解决这个问题。这意味着现有的 Node.js 应用程序和 npm 包无需任何修改即可与 Bun 无缝集成。确保这种兼容性的关键功能包括:
- 支持内置 Node.js 模块,例如
fs、path和net. - 识别全局变量,如
__dirname和process。 - 遵守 Node.js 模块解析算法,包括熟悉的
node_modules结构。
包子仍在不断发展。它专为增强开发工作流程而定制,非常适合资源有限的环境(例如无服务器功能)。Bun 背后的团队正在努力实现全面的 Node.js 兼容性以及与流行框架的更好集成
虽然 Bun 确保了与 Node.js 的兼容性,但它并不止于此。Bun附带高度优化的标准库Api可参考 BunApi,可满足开发人员最需要的功能。