對 Deno 感興趣,想嚐嚐鮮或快速入門 Deno 的小夥伴看過來,本文將從七個方面入手,帶你一步步學習 Deno 的相關知識,詳細的內容大綱以下圖所示:javascript
自從 Deno 1.0 正式發佈以後,Deno 的熱度漸漸褪去。但近期 Deno 團隊計劃刪除全部內部代碼構建時的 TS 類型檢查與捆綁,又把 Deno 再一次帶入你們的視野。html
下面咱們來經過知乎上 justjavac(迷渡大大) 一個高讚的回答來大體瞭解一下其主要緣由。java
來自 天豬 的提問: 如何評價 deno 計劃把一些內部模塊從 ts 改回 js ?來自 justjavac 的高贊回答:node
先說緣由:根本緣由是 ts 沒法爲 Deno runtime 生成高性能的 js 代碼。webpack
首先須要澄清一個誤區:Deno 並無放棄 TypeScript,Deno 依然是一個安全的 TS/JS runtime。git
編譯速度慢是一個方面,但不是根本緣由。rustc 的編譯速度也很慢,可是生成的代碼質量很高。tsc 確實也慢,若是 tsc 可以生成高性能的 js 代碼,那麼這點構建的時間成本是能夠接受的。可是目前來看 ts 沒法爲 Deno runtime 生成高性能的 js 代碼。或者說,Deno 團隊沒有找到 ts 生成高性能 js 代碼的方式。github
Deno 使用最新版 ts 和 v8,而 ts 和 v8 的實現目標都是 stage3,理論上 ts 只要簡單的作類型擦除就能夠直接運行在 v8 上。最初 Deno 團隊也是這麼想的。可是實際使用 ts 的狀況卻不是這麼理想。web
此處省略好多個字,這裏就不繼續 「搬運」 了,感興趣的小夥伴能夠仔細閱讀一下原文,文中 justjavac 詳細介紹了前因後果。chrome
原文地址:https://www.zhihu.com/questio...typescript
Deno 是一個 JavaScript/TypeScript 的運行時,默認使用安全環境執行代碼,有着卓越的開發體驗。
(圖片來源:https://deno.land/artwork)
Deno 是 Node.js 之父 Ryan Dahl 的另外一個大做,它跟 Node.js 的關係是這樣的:
"node".split("").sort().join(""); // Output: deno
那麼實際上 Deno 與 Node.js 之間有什麼區別呢?這裏阿寶哥就不展開介紹了,感興趣的小夥伴能夠閱讀 「 Deno 正式發佈,完全弄明白和 node 的區別」 這篇文章。
下面咱們步入正題,開始進入 Deno 的世界,Deno 含有如下功能特性:
Deno 是一個跨平臺的運行時,即基於 Google V8 引擎的運行時環境,該運行時環境是使用 Rust 語言開發的,並使用 Tokio 庫來構建事件循環系統。Deno 創建在 V8、Rust 和 Tokio 的基礎上,它的架構以下:
(圖片來源:https://deno.land/manual/cont...)
Rust 是由 Mozilla 主導開發的通用、編譯型編程語言。設計準則爲 「安全、併發、實用」,支持函數式、併發式、過程式以及面向對象的編程風格。Deno 使用 Rust 語言來封裝 V8 引擎,經過 libdeno
綁定,咱們就能夠在 JavaScript 中調用隔離的功能。
Tokio 是 Rust 編程語言的異步運行時,提供異步事件驅動平臺,構建快速,可靠和輕量級網絡應用。利用 Rust 的全部權和併發模型確保線程安全。Tokio 構建於 Rust 之上,提供極快的性能,使其成爲高性能服務器應用程序的理想選擇。在 Deno 中 Tokio 用於並行執行全部的異步 IO 任務。
V8 是一個由 Google 開發的開源 JavaScript 引擎,用於 Google Chrome 及 Chromium 中。V8 在運行以前將JavaScript 編譯成了機器代碼,而非字節碼或是解釋執行它,以此提高性能。更進一步,使用瞭如內聯緩存(inline caching)等方法來提升性能。有了這些功能,JavaScript 程序與 V8 引擎的速度媲美二進制編譯。在 Deno 中,V8 引擎用於執行 JavaScript 代碼。
Deno 可以在 Mac、Linux 和 Windows 上運行。Deno 是一個單獨的可執行文件,它沒有額外的依賴。你能夠經過如下方式來安裝它:
$ curl -fsSL https://deno.land/x/install/install.sh | sh
iwr https://deno.land/x/install/install.ps1 -useb | iex
scoop install deno
choco install deno
brew install deno
cargo install deno
Deno 也能夠手動安裝,只需從 github.com/denoland/deno/releases 下載一個 zip 文件。它僅包含一個單獨的可執行文件。在 Mac 和 Linux 上,你須要爲它設置執行權限。當你成功安裝以後,能夠經過執行 deno --version
命令來查看已安裝的 Deno 版本:
$ deno --version deno 1.1.2 v8 8.5.216 typescript 3.9.2
在安裝過程當中,若是遇到問題的話,你們能夠試試 justjavac(迷渡)大神提供的安裝腳本 —— deno_install。該腳本經過單行命令將 Deno 安裝到系統中(國內加速)。
使用 Shell:
$ curl -fsSL https://x.deno.js.cn/install.sh | sh
使用 PowerShell:
$ iwr https://x.deno.js.cn/install.ps1 -useb -outf install.ps1; .\install.ps1 # iwr https://x.deno.js.cn/install.ps1 -useb | iex
使用 Shell:
$ curl -fsSL https://x.deno.js.cn/install.sh | sh -s v0.41.0
使用 PowerShell:
$ iwr https://x.deno.js.cn/install.ps1 -useb -outf install.ps1; .\install.ps1 v0.41.0
更多詳細的信息能夠瀏覽 x.deno.js.cn 站點。
deno-cli 命令行界面提供了一組集成功能,讓你能夠沉浸在 Deno 的專有開發環境中。如下是 Deno 1.1.2 版本支持的全部子命令:
SUBCOMMANDS: bundle Bundle module and dependencies into single file cache Cache the dependencies completions Generate shell completions doc Show documentation for a module eval Eval script fmt Format source files help Prints this message or the help of the given subcommand(s) info Show info about cache or info related to source file install Install script as an executable lint Lint source files repl Read Eval Print Loop run Run a program given a filename or url to the module. Use '-' as a filename to read from stdin. test Run tests types Print runtime TypeScript declarations upgrade Upgrade deno executable to given version
在命令中輸入 deno 命令,你就會啓動一個 REPL(Read-Execute-Print-Loop):
$ deno Deno 1.1.2 exit using ctrl+d or close() > 0.1 + 0.2 0.30000000000000004 > const name = "阿寶哥"; undefined > console.log(name); 阿寶哥 undefined
「讀取-求值-輸出」循環(英語:Read-Eval-Print Loop,簡稱 REPL),也被稱作交互式頂層構件(英語:interactive toplevel),是一個簡單的,交互式的編程環境。這個詞經常用於指代一個 Lisp 的交互式開發環境,也能指代命令行的模式。
相信不少小夥伴都在使用 VSCode IDE 進行 Web 開發,對於 Deno 的開發者來講,必定不能錯過 Deno 官方開發的 Visual Studio Code Deno extension 擴展。
若是咱們寫 from "./hello.ts"
這樣的語句,在 VSCode 中將會出現波浪號的錯誤信息。由於默認狀況下,TypeScript 項目不須要添加 .ts
擴展名。
ts(2691): An import path cannot end with a '.ts' extension. Consider importing './hello' instead.
Deno 容許從 URL 中導入模塊,可是 TypeScript 並不支持從 URL 中導入模塊。
ts(2307): Cannot find module ' https://deno.land/x/std/log/mod'.
Deno 將遠程導入(imports)緩存在 $DENO_DIR
環境變量指定的特殊目錄中。若是未指定 $DENO_DIR
,則默認爲系統的緩存目錄。
該插件能夠將遠程導入(remote imports)解析爲本地路徑。
(本章節圖片來源:https://marketplace.visualstu...)
瞭解 VSCode Deno extension 更多的詳細信息,能夠閱讀 justjavac(迷渡) 大佬 我爲 VS Code 開發了一個 Deno 插件 這篇文章。
相信一些讀者安裝完 Deno 已經火燒眉毛了,如今咱們立馬來體驗一下 Deno 應用程序。首先打開你熟悉的命令行,而後在命令行輸入如下命令:
$ deno run https://deno.land/std/examples/welcome.ts Download https://deno.land/std/examples/welcome.ts Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts Compile https://deno.land/std/examples/welcome.ts Welcome to Deno 🦕
經過觀察以上輸出,咱們能夠知道當運行 deno run https://deno.land/std/examples/welcome.ts
命令以後,Deno 會先從 https://deno.land/std/examples/welcome.ts
URL 地址下載 welcome.ts
文件,該文件的內容是:
console.log("Welcome to Deno 🦕");
當文件下載成功後,Deno 會對 welcome.ts
文件進行編譯,即編譯成 welcome.ts.js
文件,而後再經過 V8 引擎來執行編譯生成的 JavaScript 文件。須要注意的是,若是你在命令行從新運行上述命令,則會執行緩存中已生成的文件,並不會再次從網上下載 welcome.ts
文件。
$ deno run https://deno.land/std/examples/welcome.ts Welcome to Deno 🦕
那如何證實再次執行上述命令時, Deno 會優先執行緩存中編譯生成的 JavaScript 文件呢?這裏咱們要先介紹一下 deno info
命令,該命令用於顯示有關緩存或源文件相關的信息:
$ deno info DENO_DIR location: "/Users/fer/Library/Caches/deno" Remote modules cache: "/Users/fer/Library/Caches/deno/deps" TypeScript compiler cache: "/Users/fer/Library/Caches/deno/gen"
在上述的輸出信息中,咱們看到了 TypeScript compiler cache 這行記錄,很明顯這是 TypeScript 編譯器緩存的目錄,進入該目錄後,經過一層層的查找,咱們最終在 examples
目錄下找到了 welcome.ts.js
文件:
➜ examples ls welcome.ts.buildinfo welcome.ts.js.map welcome.ts.js welcome.ts.meta
打開目錄中 welcome.ts.js
文件,咱們能夠看到如下內容:
"use strict"; console.log("Welcome to Deno 🦕"); //#sourceMappingURL=data:application/json;base64,eyJ2Z...
下面咱們來修改該文件,在文件中添加一行輸出信息 console.log("Hello Semlinker, from Cache");
,具體以下:
"use strict"; console.log("Hello Semlinker, from Cache"); console.log("Welcome to Deno 🦕"); //#sourceMappingURL=data:application/json;base64,eyJ2Z...
接着咱們在命令行中從新執行如下命令:
$ deno run https://deno.land/std/examples/welcome.ts Hello Semlinker, from Cache Welcome to Deno 🦕
那麼如今問題又來了,如何強制刷新緩存,即從新編譯 TypeScript 代碼呢?針對這個問題,在運行 deno run
命令時,咱們須要添加 --reload
標誌,來告訴 Deno 須要從新刷新指定文件:
$ deno run --reload https://deno.land/std/examples/welcome.ts Download https://deno.land/std/examples/welcome.ts Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts Compile https://deno.land/std/examples/welcome.ts Welcome to Deno 🦕
除了 --reload
標誌以外,Deno run 命令還支持不少其餘的標誌,感興趣的讀者能夠運行 deno run --help
命令來查看更多的信息。
前面咱們已經介紹瞭如何運行官方的 welcome 示例,下面咱們來介紹如何使用 Deno 建立一個簡單的 TCP echo 服務器。首先咱們建立一個 learn-deno 項目,而後在該項目下新建一個 quickstart 目錄,接着新建一個 echo_server.ts
文件並輸入如下代碼:
const listener = Deno.listen({ port: 8080 }); console.log("listening on 0.0.0.0:8080"); for await (const conn of listener) { Deno.copy(conn, conn); }
for await...of 語句會在異步或者同步可迭代對象上建立一個迭代循環,包括 String,Array,Array-like 對象(好比 arguments 或者 NodeList),TypedArray,Map, Set 和自定義的異步或者同步可迭代對象。
for await...of 的語法以下:
for await (variable of iterable) { statement }
輸入完以上代碼以後,相信不少讀者會跟我同樣,直接在命令行運行如下命令:
➜ quickstart deno run ./echo_server.ts Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.ts error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11) at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10) at Object.listen ($deno$/ops/net.ts:51:10) at Object.listen ($deno$/net.ts:152:22) at file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.ts:1:23
很明顯是權限錯誤,從錯誤信息中,Deno 告訴咱們須要設置 --allow-net
標誌,以容許網絡訪問。爲何會這樣呢?這是由於 Deno 是一個 JavaScript/TypeScript 的運行時,默認使用安全環境執行代碼。下面咱們添加 --allow-net
標誌,而後再次運行 echo_server.ts
文件:
➜ quickstart deno run --allow-net ./echo_server.ts listening on 0.0.0.0:8080
當服務器成功運行以後,咱們使用 nc
命令來測試一下服務器的功能:
➜ ~ nc localhost 8080 hell semlinker hell semlinker
介紹完如何使用 Deno 建立一個簡單的 TCP echo 服務器,咱們再來介紹一下如何使用 Deno 建立一個簡單的 HTTP 服務器。
與 TCP Server 同樣,在 quickstart 目錄下,咱們新建一個 http_server.ts
文件並輸入如下內容:
import { serve } from "https://deno.land/std@v0.50.0/http/server.ts"; const PORT = 8080; const s = serve({ port: PORT }); console.log(` Listening on <http://localhost>:${PORT}/`); for await (const req of s) { req.respond({ body: "Hello Semlinker\\n" }); }
友情提示:在實際開發過程當中,你能夠從 https://deno.land/std 地址獲取所需的標準庫版本。示例中咱們顯式指定了版本,固然你也能夠不指定版本,好比這樣: https://deno.land/std/http/se... 。
在上述代碼中,咱們導入了 Deno 標準庫 http 模塊中 serve 函數,而後使用該函數快速建立 HTTP 服務器,該函數的定義以下:
// https://github.com/denoland/deno/blob/master/std/http/server.ts export function serve(addr: string | HTTPOptions): Server { if (typeof addr === "string") { const [hostname, port] = addr.split(":"); addr = { hostname, port: Number(port) }; } const listener = Deno.listen(addr); return new Server(listener); }
serve 函數接收一個參數,其類型是 string | HTTPOptions
,其中 HTTPOptions 接口的定義以下:
/** Options for creating an HTTP server. */ export type HTTPOptions = Omit<Deno.ListenOptions, "transport">; export interface ListenOptions { /** The port to listen on. */ port: number; /** A literal IP address or host name that can be resolved to an IP address. * If not specified, defaults to `0.0.0.0`. */ hostname?: string; }
當輸入的參數類型是字符串時,serve 函數會使用 :
冒號對字符串進行切割,獲取 hostname
和 port
,而後包裝成對象賦值給 addr 參數,接着使用 addr 參數繼續調用 listen
函數進一步建立 listener
對象,最終調用 new Server(listener)
建立 HTTP 服務器。
建立完 HTTP 服務器,咱們來啓動該服務器,打開命令行輸入如下命令:
➜ quickstart deno run --allow-net ./http_server.ts Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/http_server.ts Listening on <http://localhost>:8080/
接着打開瀏覽器,在地址欄上輸入 http://localhost:8080/ 地址,以後在當前頁面中會看到如下內容:
Hello Semlinker\n
介紹完如何使用 Deno 搭建一個 HTTP 服務器,接下來咱們再來介紹如何使用 Deno 開發一個簡單的 cat
命令。在 Linux 系統中,cat
命令用於鏈接文件並打印到標準輸出設備上。 如今咱們在 quickstart 目錄下,新建一個 cat.ts
文件並輸入如下內容:
for (let i = 0; i < Deno.args.length; i++) { let filename = Deno.args[i]; let file = await Deno.open(filename); await Deno.copy(file, Deno.stdout); file.close(); }
在以上代碼中,咱們使用了 Deno 命名空間下的 3 個 API,它們的做用以下:
Deno.args
:獲取腳本接收的參數;Deno.open
:用於打開文件,返回一個 Promise 對象,resolve 後返回一個 Deno.File 對象;Deno.copy
:用於執行拷貝操做,實現從源到目標的拷貝。當遇到 EOF 或發生錯誤時,會中止拷貝操做。調用該方法後,也會返回一個 Promise 對象,resolve 後會返回已複製的字節數。因爲 Deno 是一個 JavaScript/TypeScript 的運行時,默認使用安全環境執行代碼。所以在運行 cat.ts
腳本時,咱們要設置 --allow-read
標誌 ,已容許文件系統讀訪問。即具體的腳本以下所示:
➜ quickstart deno run --allow-read cat.ts echo_server.ts
以上命令成功運行後,控制檯會輸出如下結果:
const listener = Deno.listen({ port: 8080 }); console.log("listening on 0.0.0.0:8080"); for await (const conn of listener) { Deno.copy(conn, conn); }
快速體驗完 Deno,要進行實際項目開發,咱們還得了解一下如何調試 Deno 應用程序,因此下面咱們將介紹如何使用 Chrome Devtools 和 VSCode 調試 Deno 應用程序。
Deno 支持 V8 Inspector Protocol。使用 Chrome Devtools 或其餘支持該協議的客戶端(好比 VSCode)可以調試 Deno 程序。要啓用調試功能,用 --inspect
或 --inspect-brk
選項運行 Deno,對應的選項描述以下:
--inspect=<HOST:PORT> activate inspector on host:port (default: 127.0.0.1:9229) --inspect-brk=<HOST:PORT> activate inspector on host:port and break at start of user script
--inspect
選項容許在任什麼時候間點鏈接調試器,而 --inspect-brk
選項會等待調試器鏈接,在第一行代碼處暫停執行。
讓咱們用 Chrome 開發者工具來調試一個簡單的程序,咱們將使用來自 std
的 file_server.ts,這是一個簡單的靜態文件服務。
使用 --inspect-brk
選項,在第一行代碼處暫停執行。
$ deno run --inspect-brk --allow-read --allow-net https://deno.land/std@v0.50.0/http/file_server.ts Debugger listening on ws://127.0.0.1:9229/ws/1e82c406-85a9-44ab-86b6-7341583480b1 Download https://deno.land/std@v0.50.0/http/file_server.ts Compile https://deno.land/std@v0.50.0/http/file_server.ts ...
打開 chrome://inspect
,點擊 Target 旁邊的 Inspect
。
進一步瞭解更詳細的調試說明,可訪問 https://deno.land/manual/tool... URL 地址。
Deno 能夠在 VSCode 中調試。插件的官方支持正在開發中 https://github.com/denoland/v...,固然咱們也能夠經過手動提供 launch.json
配置,來鏈接調試器:
{ "version": "0.2.0", "configurations": [ { "name": "Deno", "type": "node", "request": "launch", "cwd": "${workspaceFolder}", "runtimeExecutable": "deno", "runtimeArgs": ["run", "--inspect-brk", "-A", "<entry_point>"], "port": 9229 } ] }
注意:將 <entry_point>
替換爲實際的腳本名稱。
下面讓咱們來嘗試一下調試本地源文件,建立 server.ts
:
import { serve } from "https://deno.land/std@v0.50.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" }); }
將 <entry_point>
改成 server.ts
,而後運行。
(圖片來源:https://deno.land/manual/tool...)
(圖片來源:https://deno.land/manual/tool...)
Deno 還支持 W3C 標準規範,所以像 fetch
、setTimeout
、Blob
和 Worker
等 API 均可以被直接使用。目前 Deno 已實現瞭如下 Web APIs:
multipart/form-data
表單數據;出於篇幅考慮考慮,阿寶哥不打算介紹上面全部 Web APIs,只打算簡單介紹一下 Blob API 和 Worker API。
Blob(Binary Large Object)表示二進制類型的大對象。在數據庫管理系統中,將二進制數據存儲爲一個單一個體的集合。Blob 一般是影像、聲音或多媒體文件。在 JavaScript 中 Blob 類型的對象表示不可變的相似文件對象的原始數據。
Blob
由一個可選的字符串 type
(一般是 MIME 類型)和 blobParts
組成:
MIME(Multipurpose Internet Mail Extensions)多用途互聯網郵件擴展類型,是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。常見的 MIME 類型有:超文本標記語言文本 .html text/html、PNG圖像 .png image/png、普通文本 .txt text/plain 等。
Blob 構造函數的語法爲:
var aBlob = new Blob(blobParts, options);
相關的參數說明以下:
options:一個可選的對象,包含如下兩個屬性:
""
,它表明了將會被放入到 blob 中的數組內容的 MIME 類型。"transparent"
,用於指定包含行結束符 \n
的字符串如何被寫入。 它是如下兩個值中的一個: "native"
,表明行結束符會被更改成適合宿主操做系統文件系統的換行符,或者 "transparent"
,表明會保持 blob 中保存的結束符不變。前面咱們已經知道 Blob 對象包含兩個屬性:
Blob
對象中所包含數據的大小(以字節爲單位)。Blob
對象所包含數據的 MIME 類型。若是類型未知,則該值爲空字符串。ReadableStream
。USVString
。ArrayBuffer
。這裏咱們須要注意的是,Blob
對象是不可改變的。咱們不能直接在一個 Blob 中更改數據,可是咱們能夠對一個 Blob 進行分割,從其中建立新的 Blob 對象,將它們混合到一個新的 Blob 中。這種行爲相似於 JavaScript 字符串:咱們沒法更改字符串中的字符,但能夠建立新的更正後的字符串。
let myBlobParts = ["<html><h2>Hello Semlinker</h2></html>"]; let myBlob = new Blob(myBlobParts, { type: "text/html", ending: "transparent", }); console.log(myBlob.size + " bytes size"); console.log(myBlob.type + " is the type");
以上代碼使用 deno run deno-blob.ts
命令運行後,命令行會輸出如下結果:
37 bytes size text/html is the type
Web Worker 是 HTML5 標準的一部分,這一規範定義了一套 API,它容許一段 JavaScript 程序運行在主線程以外的另一個線程中。Web Worker 的做用,就是爲 JavaScript 創造多線程環境,容許主線程建立 Worker 線程,將一些任務分配給後者運行。
在主線程運行的同時,Worker 線程在後臺運行,二者互不干擾。等到 Worker 線程完成計算任務,再把結果返回給主線程。這樣的好處是,能夠在獨立線程中處理一些計算密集型或高延遲的任務,從而容許主線程(一般是 UI 線程)不會所以被阻塞或拖慢。
(圖片來源:https://viblo.asia/p/simple-w...)
Worker() 構造函數建立一個 Worker 對象,該對象執行指定的URL腳本。這個腳本必須遵照同源策略 。若是違反同源策略,則會拋出一個 SECURITY_ERR 類型的 DOMException。
Worker 構造函數的語法爲:
const myWorker = new Worker(aURL, options);
相關的參數說明以下:
options(可選):包含可在建立對象實例時設置的選項屬性的對象。可用屬性以下:
須要注意的是,在建立 Web Worker 的時候,可能會出現如下異常:
text/javascript
。main.ts
const worker = new Worker(new URL("worker.ts", import.meta.url).href, { type: "module", }); worker.onmessage = (e: MessageEvent) => { console.log(`Main: Received msg from deno worker - ${e.data}`); }; worker.postMessage("Hello Deno");
worker.ts
self.onmessage = (e: MessageEvent) => { console.log(`Worker: Received from main - ${e.data}`); self.postMessage("Hello Semlinker"); };
以上代碼使用 deno run --allow-read main.ts
命令運行後,命令行會輸出如下結果:
Worker: Received from main - Hello Deno Main: Received msg from deno worker - Hello Semlinker
相信接觸過 Node.js 的讀者對 Express、Hapi、Koa 這些 Web 應用開發框架都不會陌生,在 Deno 平臺中若是你也想作 Web 應用開發,能夠考慮直接使用如下現成的框架:
寫做本文時,目前 Star 數最高的項目是 Oak,下面咱們來簡單介紹一下 Oak:
A middleware framework for Deno's http server, including a router middleware.This middleware framework is inspired by Koa and middleware router inspired by koa-router.
很顯然 Oak 的的靈感來自於 Koa,而路由中間件的靈感來源於 koa-router 這個庫。若是你之前使用過 Koa 的話,相信你會很容易上手 Oak。不信的話,咱們來看個示例:
import { Application } from "https://deno.land/x/oak/mod.ts"; const app = new Application(); app.use((ctx) => { ctx.response.body = "Hello Semlinker!"; }); await app.listen({ port: 8000 });
以上示例對於每一個 HTTP 請求,都會響應 "Hello Semlinker!"。只有一箇中間件是否是感受太 easy 了,下面咱們來看一個更復雜的示例(使用多箇中間件):
import { Application } from "https://deno.land/x/oak/mod.ts"; const app = new Application(); // Logger app.use(async (ctx, next) => { await next(); const rt = ctx.response.headers.get("X-Response-Time"); console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`); }); // Timing app.use(async (ctx, next) => { const start = Date.now(); await next(); const ms = Date.now() - start; ctx.response.headers.set("X-Response-Time", `${ms}ms`); }); // Hello World! app.use((ctx) => { ctx.response.body = "Hello World!"; }); await app.listen({ port: 8000 });
爲了更好地理解 Oak 中間件流程控制,咱們來一塊兒回顧一下 Koa 大名鼎鼎的 「洋蔥模型」:
從 「洋蔥模型」 示例圖中咱們能夠很清晰的看到一個請求從外到裏一層一層的通過中間件,響應時從裏到外一層一層的通過中間件。上述代碼使用 deno run --allow-net oak/oak-middlewares-demo.ts
成功運行後,咱們打開瀏覽器,而後訪問 http://localhost:8000/ URL 地址,以後在命令行會輸出如下結果:
GET http://localhost:8000/ - 0ms GET http://localhost:8000/favicon.ico - 0ms
這裏咱們只是簡單介紹了 Oak,若是對 Oak 如何開發 REST API 感興趣的話,能夠閱讀阿寶哥 了不得的 Deno 實戰教程 這篇文章。
截止目前(2020-06-30)爲止,Deno 支持的第三方庫的數目爲 707 。
(圖片來源:https://deno.land/x)
下面咱們以你們熟悉的 lodash
爲例,來看一下如何使用第三方模塊。首先在搜索框中輸入 lodash
,對應的搜索結果以下:
(圖片來源:https://deno.land/x)
接着選擇你想要安裝的模塊,這裏阿寶哥選擇 deno_lodash
這個模塊,點擊該列表項會進入該模塊的詳情頁。而後你就能夠根據模塊的說明文檔來安裝使用模塊了,如下是文檔中該模塊的使用示例:
import _ from "https://deno.land/x/deno_lodash/mod.ts"; console.log(_.defaults({ 'a': 1 }, { 'a': 3, 'b': 2 })); // → { 'a': 1, 'b': 2 } console.log(_.partition([1, 2, 3, 4], (n:number) => n % 2)); // → [[1, 3], [2, 4]]
在 Deno 項目中可使用一個 deps.ts
文件來統一管理全部依賴,別的地方直接從 deps.ts
統一引入,例如 oak 項目的 deps.ts
以下所示:
// https://github.com/oakserver/oak/blob/main/deps.ts export { copyBytes, equal } from "https://deno.land/std@0.59.0/bytes/mod.ts"; export { Sha1 } from "https://deno.land/std@0.59.0/hash/sha1.ts"; export { HmacSha256 } from "https://deno.land/std@0.59.0/hash/sha256.ts"; // 已省略部分代碼 // 3rd party dependencies export { contentType, extension, lookup, } from "https://deno.land/x/media_types@v2.3.8/mod.ts"; export { compile, parse as pathParse, pathToRegexp, } from "https://raw.githubusercontent.com/pillarjs/path-to-regexp/v6.1.0/src/index.ts";
那麼如何查找這些模塊呢?除了在前面提到的 Deno 官網 第三方模塊 頁面查找以外,你也能夠在 pika 中尋找指定的模塊,若是搜索出來的結果能直接使用,不會報錯,代表該模塊能夠正常在 deno 中使用。
在 Deno 中若是要使用 npm 包,能夠利用 Deno 標準庫中提供的 createRequire
方法,具體使用方式以下:
import { createRequire } from "https://deno.land/std/node/module.ts"; const require = createRequire(import.meta.url); // Loads native module polyfill. const path = require("path"); // Loads extensionless module. const cjsModule = require("./my_mod"); // Visits node_modules. const leftPad = require("left-pad");
除此以外,Deno 還能夠藉助 jspm.io 的能力來調用 npm 的模塊,感興趣的小夥伴能夠閱讀 Deno藉助jspm使用npm 這篇文章。
儘管將模塊移植到 Deno 很是容易,可是你要維護兩個代碼庫卻很麻煩。因此若是你想只使用一個代碼庫來維護同時支持 Deno 和 npm 的模塊,這時你能夠考慮使用 denoify 這個工具。
denoify 是一個構建工具,該構建工具將旨在以 node 或 web 爲目標的 TypeScript 代碼庫做爲輸入,並將源文件的修改版本做爲 Deno模塊部署。
(圖片來源:https://github.com/garronej/d...)
如下是使用 denoify 開發的模塊:
感興趣的小夥伴,能夠自行了解一下上述的模塊。另外,若是你也想要在項目中使用 denoify ,那麼能夠參考這個倉庫,該倉庫會一步步教你如何在項目中配置 denoify 。
本文從七個方面入手,介紹了 Deno 入門相關的基礎知識,但願對 Deno 初學者能有一些幫助,固然有寫得很差的地方歡迎小夥伴們指出。Deno 如今還在高速地發展,標準庫還未正式發佈穩定的版本,寫做本文時,最新版本是 0.59.0。相比成熟的 Node.js 社區,Deno 社區還有很長一段路要走,感興趣的小夥伴們能夠持續關注它。
阿寶哥是在 Deno 1.0.0 發佈後才正式學習 Deno,目前也還在不斷學習中。對阿寶哥我的來講,近期比較感興趣的是 Deno Web API,所以近期也花了蠻多時間學習 Deno Web API 的實現。在學習過程當中,也遇到挺多問題的,這裏要感謝 justjavac(迷渡大大) 的耐心解答。
能看到這裏的小夥伴都是 「真愛」,最後感謝你們閱讀本教程,歡迎對 Deno 感興趣的小夥伴跟阿寶哥一塊兒交流和學習 Deno。