Deno終於有NPM Support!
2022-12-16
筆者兩年前連續寫了兩篇Node.js終結者
,分別介紹了Deno 的設計理念,以及Deno比Node.js優勝的地方。
筆者亦在第二篇文中寫了Deno的弱點
,主要在於Deno
與Node.js
龐大的NPM套件庫並不兼容,令現有的Node.js專案難以
轉會。而在11月13日推出的Deno
版本1.28,就正正是推出了廣泛之NPM Support! 馬上支援超過130萬的npm
套件。
在這篇文章之中,筆者會嘗試用Deno
,加上常見的npm套件express
及pg
套件去建立一個簡單Restful應用。
安裝
要安裝Deno
是非常簡單,只需要從官方網站直接運行安裝command。
在Mac
或Linux
的安裝方法如下:
curl -fsSL https://deno.land/x/install/install.sh | sh
在Windows
的安裝方法如下:
irm https://deno.land/install.ps1 | iex
安裝deno
之後,就可以直接運行deno
,得到以下結果。
$ deno Deno 1.28.3 exit using ctrl+d, ctrl+c, or close() >
deno
本身已支援TypeScript
及JavaScript
,無須再安裝任何其他軟件。
Express 伺服器
要完成一個簡單express
Restful應用,Deno
project 最終只需要幾個檔案。
整個專案簡潔得多,沒有package.json
也沒有tsconfig.json
!
index.ts
先由index.ts
開始,Deno
現在可以用npm:XXX
的寫法直接使用 npm
套件。
import express from "npm:express"; import { Express} from 'npm:@types/express' const app: Express = express() app.get('/',(req, res)=>{ res.json({"msg":"Hello World!"}) }) app.listen(8080)
由這段Code可見,在Deno
中使用express
與node.js
中並不相同,因為Node.js
使用CommonJS
module,而Deno
本身就運用較新的標準ES
module。 而且Deno
並不會將DefinitelyTyped
的type@types/express
與本來的express
連上關係,變相要開發者自己處理。
要運行這個index.ts
,只須直接以deno run
。
$ deno run index.ts ⚠️ ┌ Deno requests read access to <CWD>. ├ Requested by `Deno.cwd()` API ├ Run again with --allow-read to bypass this prompt. └ Allow? [y/n] (y = yes, allow; n = no, deny) >
發生何事呢?因為Deno
本身的沙盒式設計,我們需要逐個權限設定。
$ deno run --allow-net --allow-read --allow-env index.ts
不同的flag
的意思代表如下,
--allow-net
代表容許index.ts
存取網絡--allow-read
代表容許index.ts
讀取本機檔案--allow-env
代表容許index.ts
存取環境變數
然後就成功運行了一個express
伺服器。
deps.ts
不過,根據通常Deno
的開發慣例,我們並不會將所有dependencies
都放在index.ts
。 而是放在一個名為deps.ts
的檔案,這個檔案與package.json
的作用有些類似,但卻只是一個普通的Typescript
file,而非像package.json
一樣是每個npm
專案的必備檔案。
我們可以將兩句import抽出來,再放到deps.ts
。
export { default as express } from 'npm:express' export type { Request, Response, Express } from 'npm:@types/express'
在index.ts
,就只需直接從deps.ts
import 就可以了。
import { express, Express } from "./deps.ts"; const app: Express = express() app.get('/',(req, res)=>{ res.json({"msg":"Hello World!"}) }) app.listen(8080)
有需要的話,在deps.ts
亦可以直接加上版本,容易控制套件版本。
export { default as express } from 'npm:express@^4.17' export type { Request, Response, Express } from 'npm:@types/express@^4.17.15'
存取資料庫
為了簡單起見,我們會用非常受歡迎的PostgreSQL資料庫。我們亦可以運用常用的npm 套件pg
及dotenv
。
export { default as express } from 'npm:express' export type { Request, Response, Express } from 'npm:@types/express' export { default as pg } from 'npm:pg' export type {Client } from 'npm:@types/pg' export { default as dotenv } from 'npm:dotenv'
這種寫法稱為Re-export
,將由npm
套件export
出來的值再重新命名。
假設我們有一個.env
檔案,裏面有連接資料庫需要的username
及password
。
POSTGRES_DB=deno-test POSTGRES_USER=tecky POSTGRES_PASSWORD=tecky
然後就是平常的pg
設定寫法。
import { Client, Express, express, pg, dotenv } from "./deps.ts"; dotenv.config() const app:Express = express() const config = { database: Deno.env.get('POSTGRES_DB'), user: Deno.env.get('POSTGRES_USER'), password: Deno.env.get('POSTGRES_PASSWORD') } const client: Client = new pg.Client(config) await client.connect()
Deno
本身支援top level await
,因此直接運用await client.connect()
就可以連接資料庫。
當有了連接資料庫的client
,剩餘就只是簡單的express
Restful應用程式碼。
app.use(express.json()) app.get('/todos', async(req, res)=>{ const data = (await client.query("SELECT * from todos")).rows res.json(data) }) app.post('/todos',async (req ,res)=>{ const content = req.body.content await client.query("INSERT INTO todos (content) values ($1)",[content]) res.json("Hello World") }) app.listen(8080, ()=>{ console.log("Listening at http://localhost:8080") })
再用deno run
重新運行,不論GET /todos
及POST /todos
都可以成功運行了!
這段程式碼,已經開源在Github Deno NPM Example 之上
局限性
你可能讀到這裏,覺得Deno
實在太方便了! 既不需要用到npm
,又不需要用到package.json
及tsconfig.json
,是否想馬上轉會呢? 筆者在此潑個小小的冷水,Deno
在套件上確實還是有一些局限:
例如Deno
在資料庫存取上的套件比較欠缺,欠缺像knex
一樣可以跨資料庫的Database Migration
套件庫,運用knex
的npm套件庫是一個選擇,但現在時間尚早,網上資源亦比較欠奉。
大家亦可以選擇運用一些支援Deno
的套件,例如Postgres.js
及nessie
,但就可能需要找尋一下了。
總結
Deno 1.28加入了npm support
,確實令Deno
的實用性大大增強,可以活用有數百萬套件的npm
套件庫。
要將現有Node.js
專案,改為Deno
專案,難度亦已降低很多。實際是想轉會的Node.js
用戶之喜訊。
展望未來,運用Deno
的開發者會以npm
套件為主,deno
本身的套件為輔,才是最有效的做法。
Comments
Read More
Node.js終結者?青出於藍的Deno(一)
2020-08-06
有編程經驗的人,都一定會聽聞過Node.js,Node.js基于Chrome的V8引擎開發,本身能夠運行JavaScript,在前端開發(Frontend Development)、後端開發(Backend Development)、Android及iOS開發(Android & iOS Development),都有Node.js的蹤影,更帶起全JS開發的潮流,也就是大家常常在Youtube上看到的MEAN Stack(Mongodb,Express,Angular,Node.js),也是以Node.js為中心發展起來的。
Node.js終結者?青出於藍的Deno(二)
2020-08-21
返回文章的題目,Deno能否取代Node.js成為JavaScript的主要開發環境呢?筆者認為短期兩至三年內可能性都非常低,但如果未來Deno能夠解決筆者所言的兩個局限性,筆者也會躍躍欲試,將手頭上的Node.js專案加入Deno了。