Deno不只是個Javascript執行時

語言: CN / TW / HK

slug: deno-is-not-only-a-javascript-runtime title: Deno不只是Javascript執行時 date: 2023-01-20 authors: kuizuo tags: [deno, node, javascript, typescript] keywords: [deno, node, javascript, typescript]


Deno 是一個安全的 JavaScript 和 TypeScript 執行時,作者是 Ryan Dahl(也是 Node.js 的原作者)。Deno 的誕生之初是為了解決 2009 年首次設計 Node.js 時的一些疏忽。我認為這種改造動機很有道理,因為我相信每個程式設計師都希望有機會能重寫他們已有 10 年曆史的程式碼。

deno 剛出的時候就聽聞了,傳言 deno 是下一代 node.js。不過如今看來,還革不了 node.js 的命。如果要說兩者字面上的區別,Deno 的來源是 Node 的字母重新組合(Node = no + de),表示"拆除 Node.js"(de = destroy, no = Node.js)。

趁著假期學了一段時間的 deno(指文件刷了一遍),想分享本人作為 node 開發者在學習 deno 時認為的一些亮點,以及個人對 deno 與 node 見解。

開發環境

Installation | Manual | Deno

預設情況下 deno 會根據不同的系統,選擇相應的安裝目錄,以及依賴目錄,你可以配置環境變數來改變 deno 的預設行為。

這裡我選用 vscode 進行開發,安裝deno 官方外掛。此時建立一個專案工程資料夾,開啟 vscode,並建立 .vscode/settings.json 內容如下

json title='.vscode/settings.json' { "deno.enable": true, "deno.lint": true, "editor.formatOnSave": true, "[typescript]": {"editor.defaultFormatter": "denoland.vscode-deno"} }

在 vscode 中預設會將 ts 程式碼認為是 node 執行時環境,因此需要在專案工程下手動配置並啟用 deno,讓 vscode 以 deno 執行時環境來語法解析 ts 程式碼。

deno 的一些亮點💡

因為 deno 與 node 一樣,都是 javascript 執行時(deno 合理來說是 typescript 執行時)。所以在 javascript 的部分就沒什麼好說的了,主要對比 deno 相比與 node 的優勢,或說我個人覺得一些使用亮點。

官方所介紹的亮點

以下是官方所介紹的亮點,我對其做了翻譯

以下會針對部分亮點,進行個人的見解。

自帶實用工具

deno 則是自帶程式碼格式化(deno fmt)、程式碼風格(deno lint)、程式碼測試(deno test)、依賴檢查器(deno info)等等的功能。而這些在 node 中,你需要通過第三方的庫,如 eslint,jest 才能實現。

你可以在專案工程中新增配置檔案 deno.json來定製化程式碼風格(rust 中也有類似的功能),但在 node 中必須要藉助第三方的庫,或是 IDE 才能實現。

不過也能理解,在當時的程式設計環境背景下,javascript 還主要作為前端的指令碼語言使用,又怎能讓 node 來做相關規範呢?(這句話可能有點不妥)

這點我認為對開發者是否選用你這門語言的一個加分項,並且這些功能也應該作為程式語言所自帶的,有官方的背書(保證),對程式碼風格才更有所保障。

這裡有份 官方小抄 可以知道通過deno xxx等命令能夠做到 node 原本需要通過第三方庫才能實現的功能。

| Node.js | Deno | | --- | --- | | node file.js | deno run file.js | | ts-node file.ts | deno run file.ts | | npm i -g | deno install | | npm i / npm install | n/a | | npm run | deno task | | eslint | deno lint | | prettier | deno fmt | | rollup / webpack / etc | deno bundle | | package.json | deno.json / deno.jsonc / import_map.json | | tsc | deno check | | typedoc | deno doc | | jest / ava / mocha / tap / etc | deno test | | nodemon | deno run/lint/test --watch | | nexe / pkg | deno compile | | npm explain | deno info | | nvm / n / fnm | deno upgrade | | tsserver | deno lsp | | nyc / c8 / istanbul | deno coverage | | benchmarks | deno bench |

遠端匯入

與 node 不同,使用 node 通常需要從 npm 官方包來下載並導,有 npm 這樣的包管理器來統一管理這些包(package),我們通常稱這種為中心化,而 deno 與 go 的做法很像,你可以將你的封裝好的程式碼定義成一個包,並將其放在任何網路可訪問的地方,比如 github,或是私有地址,然後通過網路讀取檔案的方式來匯入,這種稱為去中心化。

:::tip

node 也不一定要用 npm 來下載模組,也可以本地模組或者私有模組。

:::

關於中心化與去中心化管理,各有優缺,這裡不做細緻討論。

以下是 deno 官方遠端匯入的程式碼示例:

Command: deno run ./remote.ts

```typescript title='remote.ts' import {add, multiply} from 'https://x.nest.land/[email protected]/source/index.js';

function totalCost(outbound: number, inbound: number, tax: number): number { return multiply(add(outbound, inbound), tax); }

console.log(totalCost(19, 31, 1.2)); console.log(totalCost(45, 27, 1.15));

/* * Output * * 60 * 82.8 / ```

而這裡的 https://x.nest.land/[email protected]/source/index.js 可以替換成任何 ES module 特性(import/export)的模組。

http 的方式執行程式碼

既然都能通過 http(cdn)遠端匯入模組,那遠端執行檔案自然也不成大問題。有時候像快捷體驗一下別人的程式碼,或是想要在瀏覽器中執行一下程式碼,這時候就可以通過 http 的方式來執行程式碼。

這裡我準備了一段程式碼,並部署到我的站點上,你可以通過如下命令得到該程式碼的執行結果(如果你有安裝 deno 的話),放心這段程式碼並無危害,就是一段簡單的 console.log 輸出。

powershell deno run https://deno.kuizuo.cn/main.ts

在第一次使用時下載並快取程式碼,你可以通過

powershell deno info http://deno.kuizuo.cn/main.ts

來檢視檔案資訊,如下

deno info 還可以檢視 deno 的相關配置,預設快取都設定在 C 盤,你也可以設定DENO_DIR 環境變數來更改 deno 目錄,可以到 Set Up Your Environment 檢視 deno 相關環境變數。

依賴管理

經常使用 node 的開發者應該對 node 的依賴感到無比厭煩,關於這部分強烈建議看 node_modules 困境,你就能知道 node 的 node_modules 設計的是有多少問題。看完你也就能知道為啥越來越多的 node 專案都使用 pnpm 作為包管理。

雖然 node 有了 pnpm 包管理器這種情況會好一些,但本質在專案目錄還是需要 node_modules 檔案。也許你用過其他語言的包管理器,你會發現基本都是將所有用到的依賴全域性快取起來,當不同的專案工程需要用到依賴時,直接去全域性快取中找,而不是像 npm 一樣,下載到專案工程目錄下,存放在 node_modules 裡。

而 deno 也是採用這種這種方式,no npm installno package.jsonno node_modules/使用 npm 包可以像下面這樣,當你使用 deno run 時便會下載好依賴置全域性快取中。

```typescript title="app.ts" {2} // @deno-types="npm:@types/[email protected]^4.17" import express from 'npm:[email protected]^4.17'; const app = express();

app.get('/', (req, res) => { res.send('Hello World'); });

app.listen(3000); console.log('listening on http://localhost:3000/'); ```

deno 剛釋出的時候,甚至還不支援 NPM 軟體包,這無非是要告訴使用者 deno 社群沒有輪子,要求使用者自己去造一個。不過 deno 團隊還是做出了比較正確的選擇,支援 npm 軟體包,並且還非常友好。

不過如果你在 deno 中使用了 npm 包,可能會存在一些相容性問題,萬一遇到了,也可以通過新增 --node-modules-dir 標識,在當前執行目錄下建立 node_modules 資料夾。詳見 --node-modules-dir flag

安全

Permissions

在 2022 年 npm 出現過一些惡性的庫,如 lodash-utils, faker.js, chalk-next。萬一你不小心安裝了上面,輕則專案無法執行,輸出無意義亂碼,重則刪除本地檔案。

又因為 npm 幾乎沒有程式碼審計的機制,任何開發者只需要有一個 npm 的賬號就能在上面隨意釋出他想釋出的包。通常來說電腦病毒都是通過隨意讀取與寫入本地檔案來達到病毒的目的,但在 deno 中,程式碼如果嘗試寫入與讀入檔案,都需要詢問開發者是否允許操作。並且在 linux 系統,你可以指定像 /usr /etc 這樣非 root 角色來操作該檔案,避免真是病毒檔案導致刪除不該刪除的檔案。

此外像命令執行,網路訪問,環境變數這些極易危害電腦的許可權,deno 都會檢測到,並做出提示告誡開發者是否允許執行。總之你能想到的電腦安全隱患,deno 都為你做好了。

內建瀏覽器環境(執行時)

這是我認為 deno 最大的亮點。

總所周知,瀏覽器的 js 程式碼有很大概率是無法直接在 node 中跑起來的,原因就是 node 的全域性物件中沒有瀏覽器的物件,如 window,document,甚至連localStorage 都有!

這說明什麼,往常如果你從別的網站扣了一段程式碼下來,想在 node 執行會發現什麼 window is not defined,xxx is not defined。如果想在 node 執行,你必須需要補齊瀏覽器的環境,此外可以藉助 js-dom,happy-dom 等 npm 包。而 window,xxx 這些全域性只有瀏覽器才定義的全域性物件在 deno 的執行時同樣定義了,可以到這裡檢視支援的 Web 平臺 API。

雖說與真實瀏覽器全域性物件有些許差異,但這也足夠讓開發者少做很多工作。比如 Web 逆向者通常要扣取瀏覽器的 js 程式碼,並補齊環境使其能夠在 node 中執行,而有了 deno 這將變得非常輕鬆!

與其說是 javascript/typescript 執行時,我更願意說是瀏覽器執行時!

Web 框架

你可以在 Web Frameworks 中看到 deno 官方所推薦的 Web 框架,其中 Fresh 也是最為推薦使用的(後續我也會嘗試使用該框架)。

而在 node 社群中,你會看到像 express,koa,nestjs 等等這種非 Node 官方或大背景的 web 框架(而且還很多),而這時對於初學者而言,就有點不知道該如何做出抉擇。

而像 java 中你完全可以不用擔心該學什麼,說學 spring 就是在學 java 這可一點都不為過。可能這也是國內 java,尤其是 spring 的開發者尤為諸多的原因。

吐槽歸吐槽,但我想表明的是在有官方的支援下,使用者和開發者能夠統一使用某個框架,一起維護與使用一個更好的框架。而不是個個 Web 框架的都有各自的優缺點,讓使用者去選擇,搞得這個框架是另一個框架的輪子一般。

所以我認為這種支援是很有必要。

公共託管服務

Project - Deploy (deno.com)

deno 像 vercel/netfily 一樣提供了一個程式碼託管服務,可以將你的 deno 應用部署上去。對,目前來看還無法部署前端應用,因為要指明一個入門檔案(main.ts)。

你可以通過 https://kuizuo.deno.dev/ 來訪問我使用 deno Deploy 所建立的一個線上專案。將會輸出一個Hello World! 的頁面。

提供一個免費的線上環境體驗,對開發者而言尤為重要,尤其是在將自己的專案成果分享給他人展示時,成就感油然而生。

node 轉 deno 開發的一些幫助

deno 相關的亮點我也差不多介紹完了,也許你對 deno 已經有一絲興趣想嘗試一番,以下我整理的對你也許有所幫助。

  • 如果你是一個 Node 使用者,考慮切換到 Deno,這裡有一個官方小抄來幫助你。

  • 如果你不想刷 deno 文件,想快速上手 deno 的話,這裡我建議推薦看看 deno 官方所推薦的deno 程式碼例子 ,能夠非常快速有效了直接瞭解 deno 標準庫以及依賴匯入匯出。

  • deno 是集成了 node 與 npm 的,也就是說允許直接使用 npm 包與 node 標準庫,如果你想用 deno 來寫 node,也行,詳看Interoperating with Node.js and npm

  • 想要在 deno 中連線資料庫,可看Connecting to Databases

  • 如果想看 deno 如何使用 deno 生態的 Web 框架建立一個 Web 服務,推薦fresh框架,並檢視該例子fresh/examples/counter

node 火嗎?

關於 deno 就暫且落下筆墨,不妨思考一個問題,node 火嗎。

作為 node 開發者,我肯定會說 node 火,不過更多是對 javascript 來說火。

:::info 2022 State of JS 2022 也結束了,不妨檢視 2022 State of JS 資料報告統計,看看 JavaScript 在 2022 年是如何發展的吧。 :::

如今 typescript 大勢所趨,說 javascript 就等同於說 typescript,而 javascript 和 node 繫結已成事實,而前端也與 javascript 所繫結,如今的前端工程師要是不會 node,都不好意思說自己是個前端工程師。就現階段看,沒了 nodejs,前端技術得倒退十年(不誇張)。

如果是在 Web 前端,Node 確實已經火的一塌糊塗了,然而它的誕生並不是為了 Web 前端,而是希望將 javascript 作為伺服器端語言發展。只是後來沒有想到的是 Node.js 在前端領域卻大放異彩,造就瞭如今大前端的盛世。

所以在 Web 後端的領域,Node 確實是不溫不火,更多的公司都寧可選主流的後端開發語言,而不是優先考慮 Node。不過倒是在 Serverless 領域中,Node 有著一席之地。

所以我想 deno 的出現,不僅是針對 Node.js 的缺陷,更是針對 Node.js 後端開發的不足。至於說 deno 能否完成原先 node 的使命,只有時間能給我們答案。

總結

從上述看來,你應該會發現 deno 並不和 node 一樣是一個純執行時環境。因為他不僅僅做了 javascript/typescript 執行時環境,還做了很多開發者好評的功能,一個為 javascript/typescript 提供更好的開發支援的產品。

但好評並不能直接決定銷量,這些功能看似可有可無,沒有激起使用者從 Node.js 切換過來的傑出之處。就我體驗完發現,好像 deno 能做的東西 node 大部分也能做,只是相對繁瑣重複一些而已。但人們更傾向於做一件繁瑣重複的事情,而不是做一個新的事情。

捫心自問,我真的很希望 deno 能火,就開發體驗而言,比 node 好用太多了,但好用的東西代表不了用的人就多,這個領域中,生態尤為重要。想要讓 node 使用者轉到 deno 開發還有很長一段路要走。

再來反問自己,我現在會將 deno 作為 node 替代品嗎,我想我和多數 node 開發者一樣,都不會將 deno 作為主力語言(因為有很多專案都已經使用node來進行開發與推動)。但作為個人開發者,尤其是 node 開發者,我認為還是非常有必要去嘗試一番 deno,親手目睹"下一代Node"。

希望本文能對你瞭解 deno 有所幫助。

相關推薦文章

Deno vs. Node.js 哪個更好 - 掘金 (juejin.cn)

為什麼 Deno 沒有眾望所歸?超越 Node.js 還要做些什麼? - 掘金 (juejin.cn)

連發明人都拋棄 node.js 了,還有前途嗎? - 知乎 (zhihu.com)

已經 2022 年了 Deno 現在怎麼樣了? - 知乎 (zhihu.com)