精讀《Deno 1.0 你須要瞭解的》

1 引言

Deno 是什麼?Deno 和 Node 有什麼關係?Deno 和我有什麼關係?前端

Deno 將於 2020-05-13 發佈 1.0,若是你還有上面的疑惑,能夠和我一塊兒經過Deno 1.0: What you need to know這篇文章一塊兒瞭解 Deno 基礎知識。node

但願你帶着疑問思考,將來 10 年看今天,會不會出現 Deno 官方生態壯大,徹底替代 Node 進而影響到 Web 生態的局面呢?這個思考結果會影響到你將來職業發展,你須要學會本身思考,並對這個思考結果負責。react

2 介紹 & 精讀

Deno 的做者是 Ryan Dahl,他是 Nodejs 背後的策劃者,曾經說過我對 Nodejs 感到遺憾的 10 件事。這也是爲何新開一個坑的緣由,但 Deno 並不定位爲 Nodejs 的替代品,從總體功能來看,Deno 有更大的野心,據個人推測是想要取代如今陳舊的先後端開發模式,讓 Deno 一統先後端開發全流程。webpack

Nodejs 是由 C++ 寫的,而 Deno 則是由 Rust 寫的,並選擇了Tokio這個異步編程框架,並使用 V8 引擎解析 Javascript,並內置了對 Ts 的解析。git

安裝

Deno 支持以下安裝方式:github

Shell:web

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

PowerShell:shell

iwr https://deno.land/x/install/install.ps1 -useb | iex

Homebrew:npm

brew install deno

Chocolatey:編程

choco install deno

腳本執行方式爲deno run,能夠類比爲node,但功能不一樣且支持遠程文件,實際上遠程依賴是 Deno 的一大特點,也是有爭議的地方:

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

在 ts 文件中容許用遠程腳本加載資源,這個後面還會提到:

import { serve } from "https://deno.land/std@v0.42.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 是默認安全的,這體如今默認沒有環境、網絡訪問權限、文件讀寫權限、運行子進程的能力。因此若是直接運行一個依賴權限的文件會報錯:

deno run file-needing-to-run-a-subprocess.ts

# error: Uncaught PermissionDenied: access to run a subprocess, run again with the --allow-run flag

能夠經過參數方式容許權限的執行,有--allow-read--allow-write--allow-net等:

deno --allow-read=/etc

上面表示/etc文件夾下的文件擁有文件讀權限。

除了直接加參數調用、Bash 腳本調用外,還能夠用 Make 運行,或者使用相似的drake啓動。

或者使用deno install命令,將腳本轉化爲一個快捷指令:

deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts

-n表示--name,能夠對這個腳本進行重命名,好比上面的例子中,serve命令就等同於deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts

標準庫

Deno 在標準庫上頗有特色,對經常使用功能提供了官方版本,保證可用性與穩定性。原文中列出了一些與 Npm 三方庫的對比:

image.png

從這個點上來看,Deno 既作運行環境又作基礎生態,緩解了 Npm 生態下選擇困難症,這件事須要辯證來看:集成了官方包對功能肯定的模塊來講是頗有必要的,並且提升了底層庫的穩定性;但 Deno 生態也有三方庫,並且本質上三方庫和官方庫在功能上沒有任何壁壘,由於實現代碼都相似,惟一區別是誰能爲其穩定性站臺,假設微軟和 Deno 同時出了基於 Npm 生態與 Deno 生態官方庫,都保證會持續維護,你更相信誰呢?官方是否有優點要取決於官方自身的實力。

內置 Typescript

Deno 內置支持了 TS,所以不須要ts-node咱們就能夠用deno run test.ts運行 Typescript 文件。值得注意的是,Deno 內部也是利用 Typescript 引擎解析爲 Js 後交由 V8 引擎解析,所以本質上沒太大的變化,只是這樣 Deno 的生態會更規範。

因爲內置了 TS 支持,天然也不須要寫tsconfig.json配置了,但你依然能夠定製它:

deno run -c tsconfig.json [file-to-run.ts]

Deno 默認還開啓了 TS 嚴格模式,因此看到這裏,能夠認爲 Deno 是爲了構建高質量理想庫而誕生的運行環境,基於已有的生態來作,但作了更多內置技術選型,這和 Facebook 的rome很像,但作的卻更完全。

其實從實現上來看,咱們基於 Javascript 生態也能寫出deno run test.ts這樣相似的引擎,只不過是由 JS 驅動執行,可能編譯還會選擇 Webpack,但 Deno 自己基於 Rust 實現,並從新實現了一套模塊加載標準,能夠說從更底層的方式從新解讀了 W3C 標準規範,以指望解決 Javascript 生態的各類痛點問題。

支持 Web 標準

Deno 還支持 W3C 標準規範,所以像fetchsetTimeout等 API 均可以被直接使用,若是你按照 Deno 支持的那幾個函數寫代碼,能夠保證在 Deno、Node、Web 三個平臺實現跨平臺運行。

雖然距離徹底實現 W3C 全部標準規範還有一些路要走,但咱們看到了 Deno 兼容規範的決心。

ESModule

模塊化是 Deno 的亮點,Deno 使用官方 ESModule 規範,但引用路徑必須加上後綴:

import * as log from "https://deno.land/std/log/mod.ts";
import { outputToConsole } from "./view.ts";

Deno 不須要申明依賴,代碼的引用路徑就是依賴申明,會包括完整的路徑以及文件後綴,也支持網絡資源,能夠擺脫 NPM 中心化的包管理模式,由於這個路徑能夠是任何網絡地址。

包管理

對於import * as log from "https://deno.land/std/log/mod.ts";這行代碼,Deno 會下載到一個緩存文件夾,用戶不會感知到這個文件夾與這個過程的存在,也就是說,Deno 環境中是沒有node_modules的。

也能夠經過deno --reload的方式強制刷新緩存。

但這裏也要辯證的看待 「Deno 去中心化」 這件事,雖然引用了網絡源,但會引起下面幾個問題:

  1. 實際上還存在一個 "node_modules",只是用戶看不到。
  2. 網絡下載速度放到運行時,第一次啓動仍是很慢。
  3. 普通模式下無 lock,必須配合deps.ts使用,這個後面會提到。

即便被打上 「中心化惡人」 的 npm 也有去中心化的一面,由於 npm 支持私有化部署,不管是速度仍是穩定性均可以由公司本身掌控,從穩定性來講仍是 npm 擁有壓倒性優點。

三方庫

Deno 還有第三方庫生態,截止目前共有221 個三方庫 "%5B%5D(https://deno.land/x/)")。

因爲 Deno 走網絡資源,咱們能夠藉助Pika提供的 CDN 服務直接引用網絡資源包:

import * as pkg from "https://cdn.pika.dev/preact@^10.3.0";

雖然這樣看上去很輕量,但對公司來講仍是須要自建一個 「Pika」 保障穩定性,以及作全球 CDN 緩存等的工做。

告別 package.json

npm 生態下包信息存放在package.json,包含但不限於下面的內容:

  • 項目元信息。
  • 項目依賴和版本號。
  • 依賴還進行分類,好比dependenciesdevDependencies甚至peerDependencies
  • 標記入口,mainmodule,還有 TS 用的typestypings,腳手架的bin等等。
  • npm scripts。

隨着標準的不斷更新,package.json信息已經很是臃腫了。

對於 Deno 來講,則使用deps.ts集中管理依賴:

export { assert } from "https://deno.land/std@v0.39.0/testing/asserts.ts";
export { green, bold } from "https://deno.land/std@v0.39.0/fmt/colors.ts";

deps.ts就是一個普通文件,只是將項目的依賴精確描述出來,這樣其餘地方引用assert時,就能夠這麼寫了:

// import { assert } from "https://deno.land/std@v0.39.0/testing/asserts.ts";
import { assert } from "./deps.ts";

若是須要鎖定依賴,能夠經過deno --lock=lock.json方式申明。

deno doc

deno doc <filename>命令能夠根據文件按照 JS Doc 規則生成文檔,同時也支持 TS 語法,好比下面這段代碼:

/** Asynchronously fulfill a response with a file from the local file
 * system. */
export async function send(
  { request, response }: Context,
  path: string,
  options: SendOptions = { root: "" }
): Promise<string | undefined> {
  // ...
}

生成文檔以下:

function send(_: Context, path: string, options: SendOptions): Promise<string | undefined>
Asynchronously fulfill a response with a file from the local file system.

deno 自己文檔就是用這個命令生成的,能夠訪問官方文檔查看使用效果。

內置工具鏈

前端 Javascript 工具鏈至關混亂,雖然業界已有 Umi 等框架作了開箱即用的封裝,但回到 Javascript 設計的初衷就是能夠在瀏覽器直接使用的,包括瀏覽器對不依賴構建工具的模塊化支持,註定了將來 Webpack 必定會被消滅。

Deno 經過內置一套工具鏈的方式解決這個問題,包括:

  • 測試:提供deno test命令與Deno.test()測試函數。
  • 格式化:提供vscode 插件
  • 編譯:提供deno bundle命令。

不過值得注意的是,在最重要的編譯環節,deno bundle目前提供的能力是相對欠缺的,好比還不支持 Tree Shaking。

用 Rust 等語言提高構建效率是業界一直在嘗試的事,好比 @陳成 就基於esbuild作了@umijs/plugin-esbuild插件用於提高 Umi 構建速度,但爲了防止生產構建產物與 Webpack 默認規則不一致,僅使用了其壓縮(minifier)功能。

對 deno 來講也同樣,目前其實沒有任何證據代表 deno 的構建結果能夠完美適配 webpack 環境,因此請勿認爲 deno 發佈了 1.0 版本就等於能夠在生產環境使用。

3 總結

正如原文結尾所說的,Deno 雖然將要發佈 1.0 版本,但仍不能徹底替代 Nodejs,這背後的緣由主要是歷史兼容成本,也就是完整支持整個 Node 生態不僅是設計的問題,更是一個體力活,須要一個個高地去攻克。

一樣 Deno 對 Web 的支持也讓人耳目一新,但仍不能放到生產環境使用,除了官方和三方生態還在逐漸完善外,deno bundle對 Tree Shaking 能力的缺失以及構建產物沒法保證與如今的 Webpack 徹底相同,這樣會致使對穩定性要求極高的大型應用遷移成本很是高。

最亮眼的改動是模塊化部分,依賴徹底去中心化從長遠來看是一個很是好的設計,只是基礎設施和生態要達到一個較爲理想的水平。

最後,讓咱們站在一個預言者角度思考一下 Deno 到底會不會火吧:

Deno 作的初心是作一個更好的 Node,但很不信,對於這種級別的生態底層工具來講,從新作一個並從新火起來的難度,不亞於從新作一個阿里巴巴並取代如今阿里的難度。也就是不一樣的時間點作同一件事,哪怕後者能夠吸收教訓,大機率也沒法複製之前成功的路線。

從 Deno 的功能來看,解決了 Node 不少痛點,其中就包括去中心化管理,有點雲開發的意思,但在 2020 年,基於 Nodejs 和 Webpack 的雲開發都搞出來了,說實話是沒有 Deno 什麼空間的。從功能上來看,開篇就說了 Deno 基於 V8 解析 Javascript,對於性能和功能都沒有革命性提高,從技術上做出突破也幾乎不可能了。

Deno 的思想確實比 Node 先進,但不能說比 Node 好十倍,則沒法撼動 Node 的生態,即使是 Node 做者本身可能也不行。

然而我上面說的可能都是錯的。

相關文章
相關標籤/搜索