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 更具優勢。

(完)

留言(18條)

照這么說,前端是不是要進軍人工智能了...

不錯,看起來既輕便又強大。

支持從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里的回調確實打腦殼

我要發表看法

«-必填

«-必填,不公開

«-我信任你,不會填寫廣告鏈接

3d字谜工作室