Deno 初探

deno.png

Deno 已经被前端圈子提及有很长一段时间了,上个月 Deno 发布了 1.0 版本,又掀起了一小股 Deno 热。Deno 到底是什么?它可以用来做什么呢?它好用吗?带着一直以来的好奇心,趁着周末的时间,认真地接触了一次 Deno。

一、什么是Deno?

Deno 是一个更安全的 JavaScript 和 TypeScript 运行时,作者 Ryan Dahl 同时也是 Node.js 的创建者。

什么是运行时?

运行时是一个运行环境,也叫运行平台,开发者可以使用指定的语言,基于这个环境开发应用。可以认为运行时就是一个舞台,能做什么事情,取决于舞台能提供什么道具。比如浏览器就是一个运行时,我们可以在浏览器上通过 JS 调用浏览器提供的 API 操作 DOM。

Deno 的作用

Deno 的作用,是让开发者可以使用 JavaScript 语言开发后端服务。

二、为什么会有Deno?

我们知道 Node.js 也是一个让开发者可以使用 JavaScript 语言开发后端服务的 JavaScript 运行时。那既然已经有一个 Node.js,而且已经非常成功,为什么还要造另一个 JavaScript 运行时 Deno ?

两年前(2018年6月),Ryan Dahl 在德国柏林召开的 JSConf EU 会议上发表了名为 “10 Things I Regret About Node.js” 的演讲,有兴趣可以到这里下载 PPT

deno-Ryan-Dahl.jpg

在分享中,Ryan 回顾了在他看来当初开发 Node.js 时留下的10大遗憾。但由于Node.js 现在已经广泛应用于各个领域,为了保证兼容性,对 Node.js 底层进行大规模改造已经不现实。会上,Ryan 宣布了他决定开发一个全新的 JavaScript Runtime 以解决当初的种种缺陷,这个项目就是 Deno。

deno-logo.png

Deno 的命名很有意思,就是把 node(no de) 倒过来 deno(de no),颇有颠覆 Node 的意味。

BTW,上个月(2020年5月15日),Deno 发布了1.0版本。

三、走近 Deno

Deno 的开发语言

相比 Node.js 使用 C++ 开发,Deno 起初使用的开发语言是 GoLang,后来改为了 Rust。并且随后把 C++ 写的 libdeno 换成了 Rust 编写的 V8 绑定:denoland/rusty_8。

Deno 目前是建立在 V8 引擎、Rust 、Tokio、TypeScript 的基础之上。

  • V8 是 chrome 浏览器内的 JavaScript 运行时。
  • Rust 是一门系统编程语言,专注于安全,尤其是并发安全。它的性能和标准C++ 不相上下。
  • Tokio 是一个给 Rust 语言使用的异步运行时,提供 event loop 和具体的 I/O 类型。
  • TypeScript 是 JavaScript 的超集。

Deno 的特性

  • 默认支持 ES Modules
  • 默认支持 TypeScript
  • 尽可能兼容 Web 标准 APIs
  • 默认采用沙箱模式运行代码,更安全
  • 去中心化第三方模块机制
  • 提供标准库

与 Node.js 的比较

  • 使用 ES 模块,不支持 require()
  • Deno 不使用 package.json
  • Deno 不使用 npm
  • Deno 中的所有异步操作返回 promise,因此 Deno 提供与 Node 不同的 API
  • Deno 需要显示指定文件、网络和环境权限
  • 第三方模块通过 URL 或者文件路径导入
  • 当未捕获的错误发生时,Deno 总是会异常退出
  • 兼容 Web 的运行时 APIs,更利于前后端的代码同构。

四、如何使用 Deno

Deno 能够在 macOS、Linux 和 Windows 上运行。Deno 是一个单独的可执行文件,它没有额外的依赖。

1.安装

在 macOS 下可以通过Shell命令安装:

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

这个方式在国内安装会很慢,慢到下不下来。。。so,不推荐。

也可以通过HomeBrew 安装:

1
brew install deno

deno-install-brew.jpg

这个方式可以安装下来,但是,安装的版本是 v0.20.0,很低的版本:

deno-version-low.jpg

并且这个版本不带 upgrade 命令,升级 deno 的时候很不方便。so,也不推荐。

安利通过国内加速器(镜像源 https://x.deno.js.cn )来安装:

1
curl -fsSL https://x.deno.js.cn/install.sh | sh

也可以指定版本:

1
curl -fsSL https://x.deno.js.cn/install.sh | sh -s v1.0.0

deno-install-x.jpg

首次安装,可以看到提示,需要手动配置一下环境变量,配置语句也已经给出:

1
2
$ touch ~/.bash_profile # 创建用户环境变量文件
$ vim ~/.bash_profile # 打开文件,将刚才命令行提示给出的配置语句粘贴进去,保存退出。

让配置立即生效:

1
$ source ~/.bash_profile

环境变量就设置好了,现在在任何一个新打开的命令行里面都可以使用 deno 命令了。

注意:如果之前使用 brew 安装过低版本的 deno,请使用 brew uninstall deno 卸载 deno 之后,再使用加速器安装高版本,不卸载直接安装高版本不会生效。(别问我为什么知道。。。都是泪。

其他操作系统环境的安装可参考 https://github.com/denoland/deno_install。

如果要升级本地的 Deno,可以运行

1
deno upgrade

还可以安装指定的版本:

1
deno upgrade --version 1.1.0

这个命令会从 github.com/denoland/deno/releases 获取最新的发布版本(一个可执行的二进制文件 zip 压缩包),然后解压并替换现有的版本。而 github release 的文件使用的是 aws,在国内访问不稳定。

So,升级也推荐使用国内加速器安装指定版本来达到目的。

2.测试安装

1
deno --version

deno-version-high.jpg

如果打印出 Deno 版本,说明安装成功。

到这里,我们就安装好 Deno ,并且可以基于 Deno 进行开发了。

3.运行一个远程的项目

跑一个远程项目(官方的demo)

1
deno run https://deno.land/std/examples/welcome.ts

可以看到在控制台输出”Welcome to Deno 🦕”。

deno-run-remote.jpg

4.运行一个本地的项目

起一个最简单的本地服务

1
2
3
4
5
6
7
8
9
// http.js
import { serve } from "https://deno.land/std@0.57.0/http/server.ts";

const s = serve({ port: 8000 });
console.log("http://localhost:8000/");

for await (const req of s) {
req.respond({ body: "Hello World\n" });
}

可以看到 Deno 在引用第三方模块的方式为 ES6 的 import 语法,并且直接通过 URL 来引入,版本号也被锁定在了 URL 中。

另外,Deno 支持 顶层的 await 语法,不用与 async 语法配对使用了。

运行:

1
deno run http.js

deno-run-local.jpg

首次引入第三方包,Deno 会去下载这个包和它的依赖,这些包会被缓存到全局,下次再引入的时候,将直接读取缓存。

这里报了一个缺少网络权限的错,这是因为 Deno 采用沙箱模式运行代码,网络权限必须通过手动添加 flag (–allow-net)来开启。

带上网络权限运行:

1
deno run --allow-net http.js

deno-run-with-net.jpg

打开localhost://8000

deno-server.jpg

可以看到一个简单的本地服务就跑起来了。

5.其他相关配置

如果我们要高效地使用 Deno,最好还需要设置一些开发环境,比如环境变量、命令行自动补全、编辑器等。

  • 环境变量

    DENO_DIR:
    这是 Deno 在本地存放生成的代码和缓存下载的模块的路径,默认为 $HOME/Library/Caches/deno。

    NO_COLOR:
    这个会关闭输出的文字颜色。

    HTTP_PROXY 和 HTTPS_PROXY :
    这两个变量用来设置 HTTP 和 HTTPS 的代理地址。

  • 命令自动补全
    通过 deno completions 命令可以生成补全脚本。他会输出到 stdout,应该将它重定向到适当的文件。

    Deno 支持的 shell 有 zsh、bash、fish、powershell、elvish。

  • 编辑器插件
    我们可以给 VS Code 配置 Deno 的插件: vscode_deno

    如果你是其他编辑器/IDE,可以参考官网推荐的插件

Deno 将来会取代 Node.js 吗?

这也是很多前端者关心的话题,网络上两种声音都有,我的看法是:会共存,但不会取代。

首先,Node.js 的作者之所以开发 Deno 只是为了兑现他心目中对 JavaScript Runtime 的一个理想实现,并不是为了取代 Node.js;

其次,Node.js 经过十多年的发展,已经很成熟了(虽然在 Ryan 的眼里不那么完美),并且已经被广泛应用。个人认为,将来 Deno 要做的事情,Node.js 都能做,如果没有特别的因素(比如潜在的安全隐患等),已经使用了 Node.js 的应用,不大会改用 Deno 重构。

所以,以我目前的认知,我认为 Deno 如果能发展起来,应该会与 Node.js 共生,而不会取代 Node.js。

不管怎样,我很钦佩 Ryan,在 Node.js 获得如此成功之后,仍然怀揣对作品的理想追求,大胆分享自己在 Node.js 中犯的“错误”,开始 Deno 的征程,并且现在 Deno 正在以飞快的速度在迭代。就在昨天,Deno 又发布了 V1.1.0。

deno-release-v1.1.0.jpg

结语

以上是我对 Deno 的一个初探,解答了什么是 Deno,它有什么作用,有哪些特点,与 Node.js 有什么不同,以及如何使用 Deno(虽然只浅浅地跑了最简单的程序,但足以让我感觉到 Deno 与 Node.js 在使用上的不同)。现在,总算对 Deno 的有了一个比较清晰的了解。

有兴趣交流的小伙伴可以在这里留言讨论:https://github.com/yc111/yc111.github.io/issues/2
Deno 交流QQ群:698469316

-End-

参考
Deno Manual:https://deno.land/manual
Deno Doc:https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts
Deno中文社区:https://denocn.org/
Deno中文开发者社区:https://deno.js.cn/
Deno中文手册:https://nugine.github.io/deno-manual-cn/
Futures 和 Tokio 项目的前世今生:https://rustcc.cn/article?id=8af74de6-1e3d-4596-94ca-c3da45509f58


文章首发于于公众号「前端手札」,喜欢的话可以关注一下哦。

qianduanshouzha-gzh.png