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
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 三方庫的對比:
從這個點上來看,Deno 既作運行環境又作基礎生態,緩解了 Npm 生態下選擇困難症,這件事須要辯證來看:集成了官方包對功能肯定的模塊來講是頗有必要的,並且提升了底層庫的穩定性;但 Deno 生態也有三方庫,並且本質上三方庫和官方庫在功能上沒有任何壁壘,由於實現代碼都相似,惟一區別是誰能爲其穩定性站臺,假設微軟和 Deno 同時出了基於 Npm 生態與 Deno 生態官方庫,都保證會持續維護,你更相信誰呢?官方是否有優點要取決於官方自身的實力。
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 生態的各類痛點問題。
Deno 還支持 W3C 標準規範,所以像fetch
、setTimeout
等 API 均可以被直接使用,若是你按照 Deno 支持的那幾個函數寫代碼,能夠保證在 Deno、Node、Web 三個平臺實現跨平臺運行。
雖然距離徹底實現 W3C 全部標準規範還有一些路要走,但咱們看到了 Deno 兼容規範的決心。
模塊化是 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 去中心化」 這件事,雖然引用了網絡源,但會引起下面幾個問題:
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 緩存等的工做。
npm 生態下包信息存放在package.json
,包含但不限於下面的內容:
dependencies
、devDependencies
甚至peerDependencies
。main
和module
,還有 TS 用的types
與typings
,腳手架的bin
等等。隨着標準的不斷更新,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 <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()
測試函數。deno bundle
命令。不過值得注意的是,在最重要的編譯環節,deno bundle
目前提供的能力是相對欠缺的,好比還不支持 Tree Shaking。
用 Rust 等語言提高構建效率是業界一直在嘗試的事,好比 @陳成 就基於esbuild作了@umijs/plugin-esbuild插件用於提高 Umi 構建速度,但爲了防止生產構建產物與 Webpack 默認規則不一致,僅使用了其壓縮(minifier)功能。
對 deno 來講也同樣,目前其實沒有任何證據代表 deno 的構建結果能夠完美適配 webpack 環境,因此請勿認爲 deno 發佈了 1.0 版本就等於能夠在生產環境使用。
正如原文結尾所說的,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 做者本身可能也不行。
然而我上面說的可能都是錯的。