Deno 运行时入门教程:Node.js 的替代品

作者: 阮一峰

日期: 2020年1月26日

这几天假期,我学习了一下 Deno。它是 Node.js 的替代品。有了它,将来可能就不需要 Node.js 了。

这篇文章就是 Deno 的一个初步介绍,尝试回答为什么 Node.js 不能满足需要,以及 Deno 能够带给我们什么?

以下内容主要基于 Bert BelderRyan Dahl 的最新演讲。

0、

进入主题之前,先说一下 Deno 这个词怎么发音。

两种发音,"德诺"和"蒂诺",我都听到过。看起来,"蒂诺"这个发音应该更合适一些,因为 Deno 的标志是一只恐龙。恐龙(dinosaur)的英文缩写正是 dino。

1、

Deno 是 Ryan Dahl 在2017年创立的。

Ryan Dahl 也是 Node.js 的创始人,从2007年一直到2012年,他后来把 Node.js 移交给了其他开发者,不再过问了,转而研究人工智能。

他始终不是很喜欢 Python 语言,久而久之,就想搞一个 JavaScript 语言的人工智能开发框架。等到他再回过头捡起 Node.js,发现这个项目已经背离了他的初衷,有一些无法忽视的问题。

2、

首先,过去五六年,JavaScript 语言脱胎换骨,ES6 标准引入了大量新的语法特性。其中,影响最大的语法有两个:Promise 接口(以及 async 函数)和 ES 模块。

Node.js 对这两个新语法的支持,都不理想。由于历史原因,Node.js 必须支持回调函数(callback),导致异步接口会有 Promise 和回调函数两种写法;同时,Node.js 自己的模块格式 CommonJS 与 ES 模块不兼容,导致迟迟无法完全支持 ES 模块。

其次,Node.js 的模块管理工具 npm,逻辑越来越复杂;模块安装目录 npm_modules 极其庞杂,难以管理。Node.js 也几乎没有安全措施,用户只要下载了外部模块,就只好听任别人的代码在本地运行,进行各种读写操作。

再次,Node.js 的功能也不完整,导致外部工具层出不穷,让开发者疲劳不堪:webpack,babel,typescript、eslint、prettier......

3、

由于上面这些原因,Ryan Dahl 决定放弃 Node.js,从头写一个替代品,彻底解决这些问题。deno 这个名字就是来自 Node 的字母重新组合(Node = no + de),表示"拆除 Node.js"(de = destroy, no = Node.js)。

跟 Node.js 一样,Deno 也是一个服务器运行时,但是支持多种语言,可以直接运行 JavaScript、TypeScript 和 WebAssembly 程序。

它内置了 V8 引擎,用来解释 JavaScript。同时,也内置了 tsc 引擎,解释 TypeScript。它使用 Rust 语言开发,由于 Rust 原生支持 WebAssembly,所以它也能直接运行 WebAssembly。它的异步操作不使用 libuv 这个库,而是使用 Rust 语言的 Tokio 库,来实现事件循环(event loop)。

4、

你可能会问,为什么使用 Rust,而不是 C++(Node.js 的开发语言)?

主要原因是 Rust 提供了很多现成的模块,对 Deno 项目来说,可以节约很多开发时间。

5、

Deno 本身也是 Rust 的一个模块。如果你想在 Rust 里面使用 V8 引擎,就可以加载 Deno。它等于是一个 V8 的包装层,提供一些底层 API,让你跟 V8 引擎互动。

6、

Deno 只有一个可执行文件,所有操作都通过这个文件完成。它支持跨平台(Mac、Linux、Windows)。

7、

Deno 具有安全控制,默认情况下脚本不具有读写权限。如果脚本未授权,就读写文件系统或网络,会报错。

必须使用参数,显式打开权限才可以。

  • --allow-read:打开读权限,可以指定可读的目录,比如--allow-read=/temp
  • --allow-write:打开写权限。
  • --allow-net=google.com:允许网络通信,可以指定可请求的域,比如--allow-net=google.com
  • --allow-env:允许读取环境变量。

8、

Deno 支持 Web API,尽量跟浏览器保持一致。

它提供 window 这个全局对象,同时支持 fetch、webCrypto、worker 等 Web 标准,也支持 onload、onunload、addEventListener 等事件操作函数。

此外,Deno 所有的异步操作,一律返回 Promise。

9、

Deno 只支持 ES 模块,跟浏览器的模块加载规则一致。没有 npm,没有 npm_modules 目录,没有require()命令(即不支持 CommonJS 模块),也不需要package.json文件。

所有模块通过 URL 加载,比如import { bar } from "https://foo.com/bar.ts"(绝对 URL)或import { bar } from './foo/bar.ts'(相对 URL)。因此,Deno 不需要一个中心化的模块储存系统,可以从任何地方加载模块。

但是,Deno 下载模块以后,依然会有一个总的目录,在本地缓存模块,因此可以离线使用。

10、

由于 Deno 只支持从 URL 加载模块,导致 Node.js 的模块加载写法都会失效。


import React from "react";
import { Box, Grid } from "@material-ui/core";
import { initializeApp } from "firebase/app";

上面的写法在 Deno 里面都是非法的。

Deno 的所有模块都要通过入口脚本加载,不能通过模块名加载,所以必须带有脚本后缀名。

11、

Deno 原生支持 TypeScript 语言,可以直接运行,不必显式转码。

它的内部会根据文件后缀名判断,如果是.ts后缀名,就先调用 TS 编译器,将其编译成 JavaScript;如果是.js后缀名,就直接传入 V8 引擎运行。

12、

Deno 内置了开发者需要的各种功能,不再需要外部工具。打包、格式清理、测试、安装、文档生成、linting、脚本编译成可执行文件等,都有专门命令。

执行deno -hdeno help,就可以显示 Deno 支持的子命令。

  • deno bundle:将脚本和依赖打包
  • deno eval:执行代码
  • deno fetch:将依赖抓取到本地
  • deno fmt:代码的格式美化
  • deno help:等同于-h参数
  • deno info:显示本地的依赖缓存
  • deno install:将脚本安装为可执行文件
  • deno repl:进入 REPL 环境
  • deno run:运行脚本
  • deno test:运行测试

13、

Deno 的安装可以参考官网首页,但是你可以直接去 GitHub 仓库的发布页,下载编译好的可执行文件(上图)。

下载 Deno 以后,查看一下版本。


$ deno --version
deno 0.31.0
v8 8.1.108
typescript 3.7.2

命令行直接运行deno,就会进入 REPL 环境。


$ deno
> console.log(1,2,3)
1 2 3
undefined
> 

14、

下面,运行一个 TypeScript 的远程脚本,这是官网给出的例子


$ deno run \
https://deno.land/std/examples/curl.ts \
https://example.com

上面例子中,Deno 执行远程脚本curl.ts,用这个脚本去抓取网址example.com。但是,运行后报错,表示没有网络通信的权限。

我们给予 Deno 网络通信的权限,就可以顺利执行。


$ deno run --allow-net \
https://deno.land/std/examples/curl.ts \
https://example.com

15、

现在,Deno 最新版本是 0.31。根据规划,1.0 应该会在今年上半年发布。

Deno 还处在密集开发中,功能不稳定,不建议用于生产环境。但是,它已经是一个可用的工具,大家可以多试用,熟悉它的用法。我相信,设计上的诸多优点,将会使它比 Node.js 更具优势。

(完)

留言(38条)

照这么说,前端是不是要进军人工智能了...

不错,看起来既轻便又强大。

支持从URL导入包, deno的生态 岂不是从一开始就很庞大...

引用foxDaxian的发言:

照这么说,前端是不是要进军人工智能了...

TensorFlow本来就有js版本。其实PYTHON的运行效率跟node的差别是数量级级的。

deno可能会是未来的趋势之一,期待!

春节期间笔耕不辍,加油

小白请教下怎么加速下载deno鸭...

一定会取代 nodejs 的,因为在编程里方便高效是永远的追求,deno 是一种迭代。

我对着npm就是一脚!对web开发人员更加友好了!

runtime翻译为“runtime运行环境”会不会更好,运行时虽然也对,但是总有点莫名其妙的感觉

恐龍的發音是 /ˈdaɪnəsɔːr/
所以德諾更合適,
可以聽聽Ryan Dahl怎麽念的:
https://www.youtube.com/watch?v=z6JRlx5NC9E

不需要package.json,直接从url加载模块
不会更难管理么,到处都是,都不知道加载了哪些模块

“不需要package.json,直接从url加载模块
不会更难管理么,到处都是,都不知道加载了哪些模块”
那也是开发人员自己引入的呀,本地也有保存的,一样的呀(你的意思是没有包管理审核)
我的一个flutter项目,里面好几个插件不更新,导致我都没法更新flutter最新版,证明有包管理也没用。

怎么我看到另一个开发者说Deno是使用Golang开发的?https://studygolang.com/articles/13101

引用万里的发言:

怎么我看到另一个开发者说Deno是使用Golang开发的?https://studygolang.com/articles/13101

Deno早期是Golang + TypeScript的,后来因为Golang和V8的GC问题,Ryan下了大工夫把golang统统换成没有GC的Rust了

好难过,nodejs还没有玩好,好好体验过他的魅力,现在deno又来插脚,????

deno 是 no de交换前后位置得到的名字

优点感觉挺不错的,但是不能用模块名导入感觉不太方便啊
不过nodejs里的回调确实打脑壳

看起来很棒哦,我非常看好这种优雅的使用方式,马上要出正式版了,花点功夫学习下!

我现在手中有个项目,享用NODEJS来做, 需要调用系统注册的COM组件,网上找不到任何方法,这个到底设计到NODE哪一块,是否可行,要不然真的项目选型就浪费很多时间了

还是 Common Lisp 比较好用

引用Hugh的发言:

“不需要package.json,直接从url加载模块
不会更难管理么,到处都是,都不知道加载了哪些模块”
那也是开发人员自己引入的呀,本地也有保存的,一样的呀(你的意思是没有包管理审核)
我的一个flutter项目,里面好几个插件不更新,导致我都没法更新flutter最新版,证明有包管理也没用。

依赖怎么解决?

deno 为啥不是 define node

看起来非常便利,支持!

我觉得很赞!期待deno V1.0。争当第一个吃螃蟹的。

引用下manual.md里提到的deno设计哲学:

Philosophy

Deno aims to be a productive and secure scripting environment for the modern programmer.

Deno will always be distributed as a single executable. Given a URL to a Deno program, it is runnable with nothing more than the 10 megabyte zipped executable. Deno explicitly takes on the role of both runtime and package manager. It uses a standard browser-compatible protocol for loading modules: URLs.

Among other things, Deno is a great replacement for utility scripts that may have been historically written with bash or python.

期待早日实装,想用js尝试ai。

取代node还是需要一定的时间去积累

我正在學node,知道deno今年可能發布版本目前噴鼻血中

引用SimonAking的发言:

支持从URL导入包, deno的生态 岂不是从一开始就很庞大...

并不是,传统npm包全都没法用的。必须要基于deno的包。或者是原生包。

引用Aloha的发言:

Deno早期是Golang + TypeScript的,后来因为Golang和V8的GC问题,Ryan下了大工夫把golang统统换成没有GC的Rust了

玩node那帮人都搞golang了,我是学golang还是学rust好呢哈哈

新技术的发展是必须的,前端产业的技术几年前就没有更新了,倒还挺期待这个技术,力争做吃螃蟹的人。

确实,node_modules太复杂了,头疼

引用zz的发言:

玩node那帮人都搞golang了,我是学golang还是学rust好呢哈哈

谷歌的Fuchsia OS支持的开发语言中包含Rust而不包含Golang,亲儿子都抛弃了,你说呢?

能够内置工具真的太方便了,最近学习webpack,babel感觉有些绕,相互耦合性很高。

引用展翼骐骥的发言:

TensorFlow本来就有js版本。其实PYTHON的运行效率跟node的差别是数量级级的。

不懂就问,意思是python效率高还是node效率高?

就目前形势来看,npm是全球最大的包管理仓库没有之一,npm是基于node环境下运行的,所以,取代node并不是很容易,当然就deno的开发方向,个人感觉是对node代码的整合和规范,当然也有各自的优势,但是可以确定的是,很长一段时间都要继续使用node。

deno是ry最初的想法回归,本来node就是期待用来简化后端的,没想到玩成了前端的生态。deno前景鸿远,让JavaScript在后端应用层打下了更坚固的位置。如果能出一款一统各种端的语言,就像秦始皇统一汉语一样[滑稽],无疑成为IT业界的历史时刻啊,那时候解放程序员重复学习的脑袋,注重业务功能实践,将会步入软件鼎盛之时,到处都有软件,到处都有智能,打个车只需讲一句话就直接传上云招来车,连路灯都联网,我希望这门语言会是ECMAScript[滑稽]。

我要发表看法

«-必填

«-必填,不公开

«-我信任你,不会填写广告链接