自從 deno 1.0 發布以來,有關 deno 的文章很多,大多數都是在討論怎么安裝 deno 、deno 有哪些特點 、deno 和 node 有哪些異同、deno是不是 node 的替代品等。咱們今天不討論這些,畢竟 Talk is cheap. Show me the code! 親自體驗一把 deno 開發帶來的快感、用 deno 搞一個“企業級”應用:deno-supermarket,難道不香嗎?
deno 常見的一些坑
在實戰之前,還是先來介紹幾個我在剛接觸 deno 時遇到的小坑。
權限標志符位置的問題
我們都知道, deno 默認是安全的,就是導致了默認情況下是不允許訪問網絡、讀寫文件等。比如有個名為 index.ts 的文件內容如下:
import { serve } from "https://deno.land/std@0.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" });
}
如果直接執行 deno run index.ts
, 會報錯:
error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
所以我們很自然的就會在啟動命令的最后加上 --allow-net
,如下:
deno run index.ts --allow-net
但是,這樣仍然會報錯。查了資料才知道 ,--allow-net
、--allow-read
之類的標志是不可以放到文件名后面的,必須緊跟在 deno run
后面,比如,如下才是正確的:
deno run --alow-net index.ts
為什么調換了位置就不行呢? issue 上的回答是,如果 --allow-net
跟在文件名后面,是傳給 js 腳本的,而不是傳給 deno 的。想了解更多的,可以看這個 confused by order of cli option flags。反正,記住一點就行:權限標志一定要跟在 deno run
后面!
因為我們前端同學大多數平時很少寫后台,不太清楚安全的重要性,為了避免遇到各種權限問題,我建議平時在寫一些練手項目時,直接用 deno run -A
來啟用全部的權限。(這只是方便調試,在生產環境中一定要慎用!)
不穩定的 API
因為實戰過程中使用了 mongodb , 所以需要引入 Deno 的第三方模塊 mongo,然而在啟動項目會報錯:
error: TS2339 [ERROR]: Property 'openPlugin' does not exist on type 'typeof Deno'.
查了一下,發現是因為 openPlugin
這個方法目前還不穩定。默認情況下,deno 只會提供穩定的 api。如果需要開啟不穩定 api,可以添加 --stable
標志。比如:
deno run -A --unstable index.ts
可能有人會問,-A
和 --unstable
的位置調換會不會有問題。這個親測過不會有問題。只要標志符在文件名稱之前就行了。
還有個問題,到底哪些是穩定 API,哪些是不穩定 API 呢?其實 deno 官方文檔已經幫我們分好類的了,入口地址分別是:
如果你懷疑 --unstable
的作用,可以使用下面的方法打印出 Deno
上的所有成員:
console.log(Object.keys(Deno).length)
使用 deno run --unstable index.ts
輸出的結果是 117,使用 deno run index.ts
輸出的結果是 88 。說明穩定的 api 有 88 個,不穩定的有 29 個。
deno 的一些使用技巧
從 node 切換到 deno, 我們的開發思維也要隨之轉變。所以,我們再來看看 deno 的一些和 node 不一樣的開發技巧。
如何管理版本?
剛開始我也很疑惑:沒有了 package.json
, 那怎么控制各依賴的版本呀?比如,我們有10個文件都依賴了 mongo@v0.0.6
, 那每個文件都使用以下代碼進行引入:
import { init, MongoClient } from 'https://deno.land/x/mongo@v0.6.0/mod.ts'
可是有一天,我突然想把 0.6.0 升級到 0.7.0, 那怎么辦呢?一個個文件的進行替換容易漏掉,當然也可以全局搜索批量替換 。但是這種效率都不是很高。
官方給出的推薦做法是,使用 deps.ts
文件來引入遠程文件,並管理版本。(當然 ,文件名稱不一定叫做 deps.ts
, 你也可以改成其他的名稱)。具體做法就是,把所有用到的遠程依賴,都在 deps.ts
中引入 ,並且通過 Re-export
手段導出各依賴,然后其他文件就可以從 deps.ts
中拿到所需要的依賴了。
回到剛才說10個文件都依賴到 mongo
的問題,如果改成 deps.ts
文件來統一管理是這樣的:
export * from 'https://deno.land/x/mongo@v0.6.0/mod.ts'
然后那些需要用到 mongo 的文件,不要直接從遠程引入,而是從 deps.ts
中引入,如下:
import { init, MongoClient } from '../pathTo/deps.ts';
如果需要升級的話,我們可以直接把 deps.ts
里面的 mongo 地址中的 0.6.0
改成 0.7.0
就行了。
另外,有一點和 npm 類似的是,如果沒有指定版本號,即遠程地址中沒有指定版本,比如:
export * from 'https://deno.land/x/mongo/mod.ts'
就會默認安裝最新版的依賴。
如何查找一些對我有用的 deno 庫?
使用 node ,可以到 npm 上查找一些庫。deno 也有類似的平台,目前分為兩種庫,一種是官方標准的,另外一種是第三方的。標准庫可以到這里查找:Deno Standard Modules。第三方庫可以到這里查找: Deno Third Party Modules
實戰: 使用 deno 開發一個具備增刪查改的商城系統
OK, 具備以上的知識點,現在可以實戰了。首先,需要保證你的電腦安裝了 deno 1.0 。另外,由於用到了 mongodb ,所以需要你的電腦也要安裝 mongodb。
界面
先來看看我們的商城的界面:
麻雀雖小五臟俱全哈!具備添加商品、查詢商品、刪除商品、修改商品的功能。這是典型的 REST API 風格的系統 。
項目結構
然后再來看看項目結構:
- .deno_plugins: 這是 mongo 模塊所下載的動態鏈接庫,不用關注它。
- congig/db.ts: 這是連接 mongodb 的相關配置文件。目前寫死的端口號是 27017 , 如果你的 mongodb 端口不是這個,可以在這個文件里面修改。
- controllers/goods.ts: 這是實現增刪查改的邏輯代碼
- public/index.html: 這是前端靜態頁面,跟 deno 無關的,我們只需要用 deno 來服務該目錄就行。
- deps.ts: 用來管理遠程依賴庫,然后 Re-export 出去給其他文件使用。
- server.ts 入口文件,跟我們用 epress 或 koa 時的入口 文件 app.js 類似。
依賴模塊的選擇
因為該項目涉及到了前后端,如果使用 node 的話,一般會選擇 express 或 koa。同樣的,我們使用 deno 也要選擇對應的框架 ,不然的話,http服務以及路由跳轉等都不是那么容易處理的。deno 上的這類框架,比較多人 star 的是 oak 和 abc,這里我們選擇使用 abc。
另外,因為使用 mongodb , 所以還需要引入 mongo
結束語
好啦,對於 deno 初體驗就寫到這啦, 具體的代碼這里不打算貼出來了,有興趣的可以前往 github 查看:
有問題的可以一起交流學習哈~