为什么我不建议用deno和bun

6 min read,created at 2024-10-13
nodedenobunruntimejs

最近deno发布了2.0版本,主键开始兼容node了,连同之前性能著称的bun。我们重新来对比下这三个js的运行时。大多数时候官方都会宣传自己的优点,只有真正使用的时候才会发现有很多缺点。我个人尤其在意的是与node的兼容性。像deno早期版本甚至完全不兼容node,也不能用npm已有的包,这显然不会被大众接受。

只有很好的兼容了node,才有可能被使用,如果不兼容node,我为什么要去学习一个新的小众的东西来替换呢?我觉得性能和易用性都不足以说服让我放弃node,因为选择js运行时更多的是为了简单通用,而不是性能,不然为什么不选择用golang呢。另外易用性上虽然node项目要添加很多配置eslint tsconfig等,但是简单项目本来也可以不配置,且目前主流框架的脚手架都会帮忙配置好。

包管理与下载的兼容

node采用package.json文件来进行包管理,使用npm install指令安装所有的依赖,依赖包的安装位置是当前目录下的node_modules目录。有一些下载更快的衍生下载工具pnpm yarn等,不作为本文的讨论范围。deno在2.0版本才兼容,使用deno install安装,但是安装的库不在node_modules目录,而是全局目录,为了多项目依赖共用。这一点上没兼容,但是并没有实质影响,也还好。bun install则是完全兼容了node的依赖安装。

我们以当前这个笔记项目为例来看下下载所有依赖需要多久。node(npm10.8.2)(版本v20.17.0)用时33s。

deno2.0.0因为是下载node项目,所以需要从npm上下载包,而且都是v8运行时,最终下载时间比node更久是48s。

bun1.1.30下载速度明显更快。

std库的兼容

写这样一段简单的js代码,用bun deno分别运行,会发现deno是不识别require的,导致无法正常运行,而bun本着尽量兼容node的思想,是能够正常运行的。

js-test.js
var fs = require('fs');
var path = require('path');

var content = fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8');

console.log(content);

虽然deno2已经尽量去兼容node了,但是代码还是需要有改动,对于node的包要用node:前缀,而且需要用import引入,而非require

js-test.js
-var fs = require('fs');
-var path = require('path');
+import fs from 'node:fs'
+import path from 'node:path'

+const __dirname = new URL('.', import.meta.url).pathname;

var content = fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8');

console.log(content);

虽然deno的改动令人沮丧,但是bun也并非完全兼容,当我用bun运行当前博客系统(next应用)的时候,会出现大量的下列报错。

NotImplementedError: worker_threads.Worker option "stderr" is not yet implemented in Bun.
NotImplementedError: worker_threads.Worker option "resourceLimits" is not yet implemented in Bun.

反倒是deno在运行next项目的时候并没有报错是正常运行的。

如何选择

我个人感觉抛开兼容性的问题,性能、编译、易用这些都是扯淡。所以我还是会使用node

如果是为了尝试下的话,我可能更愿意尝试下deno,因为他有免费的云平台,可以托管一些小的应用。bun,虽然性能确实很好,但实在是不想花时间来踩坑去用来部署服务.

此外,bun没有打包独立运行的二进制文件的能力,nodejspkg工具,虽然vercel官方已经不维护,最多支持到node18版本,但是有人fork了这个项目,继续提供新版本的支持。deno自带了这个能力,需要deno init初始化当前项目,然后deno compile xxx.js即可。编译出来的文件大小会发现deno的要更大一些(89M vs 54M),可见他的运行时核心应该比node要大。