Deno 是一个安全的 JavaScript 和 TypeScript 运行时,作者是 Ryan Dahl(也是 Node.js 的原作者)。Deno 的诞生之初是为了解决 2009 年首次设计 Node.js 时的一些疏忽。我认为这种改造动机很有道理,因为我相信每个程序员都希望有机会能重写他们已有 10 年历史的代码。
deno 刚出的时候就听闻了,传言 deno 是下一代 node.js。不过如今看来,还革不了 node.js 的命。如果要说两者字面上的区别,Deno 的来源是 Node 的字母重新组合(Node = no + de),表示"拆除 Node.js"(de = destroy, no = Node.js)。
趁着假期学了一段时间的 deno(指文档刷了一遍),想分享本人作为 node 开发者在学习 deno 时认为的一些亮点,以及个人对 deno 与 node 见解。
开发环境
默认情况下 deno 会根据不同的系统,选择相应的安装目录,以及依赖目录,你可以配置环境变量来改变 deno 的默认行为。
这里我选用 vscode 进行开发,安装deno 官方插件。此时创建一个项目工程文件夹,打开 vscode,并创建 .vscode/settings.json
内容如下
{
"deno.enable": true,
"deno.lint": true,
"editor.formatOnSave": true,
"[typescript]": { "editor.defaultFormatter": "denoland.vscode-deno" }
}
在 vscode 中默认会将 ts 代码认为是 node 运行时环境,因此需要在项目工程下手动配置并启用 deno,让 vscode 以 deno 运行时环境来语法解析 ts 代码。
deno 的一些亮点💡
因为 deno 与 node 一样,都是 javascript 运行时(deno 合理来说是 typescript 运行时)。所以在 javascript 的部分就没什么好说的了,主要对比 deno 相比与 node 的优势,或说我个人觉得一些使用亮点。
官方所介绍的亮点
以下是官方所介绍的亮点,我对其做了翻译
-
提供web 平台功能,采用网络平台标准。例如,使用 ES 模块、Web worker 和支持
fetch()
。 -
默认安全。除非显式启用,否则无法访问文件、网络或环境。
-
支持开箱即用的 TypeScript。
-
提供单个可执行文件 (
deno
)。 -
为编辑器提供内置的开发工具,如代码格式化程序 (deno fmt)、linter (deno lint)、测试运行程序(deno test)和语言服务器。
-
拥有一组经过审查(审核)的标准模块,保证与 Deno 一起使用。
-
支持使用 现有的 npm 模块
以下会针对部分亮点,进行个人的见解。
自带实用工具
deno 则是自带代码格式化(deno fmt
)、代码风格(deno lint
)、代码测试(deno test
)、依赖检查器(deno info
)等等的功能。而这些在 node 中,你需要通过第三方的库,如 eslint,jest 才能实现。
你可以在项目工程中添加配置文件 deno.json来定制化代码风格(rust 中也有类似的功能),但在 node 中必须要借助第三方的库,或是 IDE 才能实现。
不过也能理解,在当时的编程环境背景下,javascript 还主要作为前端的脚本语言使用,又怎能让 node 来做相关规范呢?(这句话可能有点不妥)
这点我认为对开发者是否选用你这门语言的一个加分项,并且这些功能也应该作为编程语言所自带的,有官方的背书(保证),对代码风格才更有所保障。
这里有份 官方小抄 可以知道通过deno xxx
等命令能够做到 node 原本需要通过第三方库才能实现的功能。
Node.js | Deno |
---|---|
node file.js | deno run file.js |
ts-node file.ts | deno run file.ts |
npm i -g | deno install |
npm i / npm install | n/a |
npm run | deno task |
eslint | deno lint |
prettier | deno fmt |
rollup / webpack / etc | deno bundle |
package.json | deno.json / deno.jsonc / import_map.json |
tsc | deno check |
typedoc | deno doc |
jest / ava / mocha / tap / etc | deno test |
nodemon | deno run/lint/test --watch |
nexe / pkg | deno compile |
npm explain | deno info |
nvm / n / fnm | deno upgrade |
tsserver | deno lsp |
nyc / c8 / istanbul | deno coverage |
benchmarks | deno bench |
远程导入
与 node 不同,使用 node 通常需要从 npm 官方包来下载并导,有 npm 这样的包管理器来统一管理这些包(package),我们通常称这种为中心化,而 deno 与 go 的做法很像,你可以将你的封装好的代码定义成一个包,并将其放在任何网络可访问的地方,比如 github,或是私有地址,然后通过网络读取文件的方式来导入,这种称为去中心化。
关于中心化与去中心化管理,各有优缺,这里不做细致讨论。
以下是 deno 官方远程导入的代码示例:
import { add, multiply } from 'https://x.nest.land/ramda@0.27.0/source/index.js'
function totalCost(outbound: number, inbound: number, tax: number): number {
return multiply(add(outbound, inbound), tax)
}
console.log(totalCost(19, 31, 1.2))
console.log(totalCost(45, 27, 1.15))
/**
* Output
*
* 60
* 82.8
*/
而这里的 https://x.nest.land/ramda@0.27.0/source/index.js
可以替换成任何 ES module 特性(import/export)的模块。
http 的方式运行代码
既然都能通过 http(cdn)远程导入模块,那远程运行文件自然也不成大问题。有时候像快捷体验一下别人的代码,或是想要在浏览器中运行一下代码,这时候就可以通过 http 的方式来运行代码。
这里我准备了一段代码,并部署到我的站点上,你可以通过如下命令得到该代码的执行结果(如果你有安装 deno 的话),放心这段代码并无危害,就是一段简单的 console.log 输出。
deno run https://deno.kuizuo.cn/main.ts
在第一次使用时下载并缓存代码,你可以通过
deno info http://deno.kuizuo.cn/main.ts
来查看文件信息,如下
deno info 还可以查看 deno 的相关配置,默认缓存都设置在 C 盘,你也可以设置DENO_DIR 环境变量来更改 deno 目录,可以到 Set Up Your Environment 查看 deno 相关环境变量。
依赖管理
经常使用 node 的开发者应该对 node 的依赖感到无比厌烦,关于这部分强烈建议看 node_modules 困境,你就能知道 node 的 node_modules 设计的是有多少问题。看完你也就能知道为啥越来越多的 node 项目都使用 pnpm 作为包管理。
虽然 node 有了 pnpm 包管理器这种情况会好一些,但本质在项目目录还是需要 node_modules 文件。也许你用过其他语言的包管理器,你会发现基本都是将所有用到的依赖全局缓存起来,当不同的项目工程需要用到依赖时,直接去全局缓存中找,而不是像 npm 一样,下载到项目工程目录下,存放在 node_modules 里。
而 deno 也是采用这种这种方式,no npm install
,no package.json