从 Node 到 Deno
我收集了一些 Node 中最常用的主题,并寻找 Deno 的替代方案。首先我想说明,许多当前的 Node.js 模块都可以都可以用在 Deno 中。由于许多模块都是可重用的,所以没有必要为所有方法去寻找替代方案。你可以访问 pika.dev 查找可以在 Deno 中使用的模块。
本文将涵盖以下内容:
Electron
通过 Node.js,我们可以使用 Electron 创建桌面程序。Electron 使用 Chromium 作为接口来运行 Web 环境。但是 Electron 可以在 Deno 中使用吗?有其他选择吗?

好吧,现在 Electron 还不能在 Deno 下执行,必须寻找替代方案。由于 Deno 是用 Rust 写的,所以可以用 web-view rust 绑定 (https://github.com/Boscop/web-view) 在 Deno 中运行桌面程序。
这样,我们可以使用本机操作系统的 webview 视图来运行任意 webview。
Repo: https://github.com/eliassjogreen/deno_webview
1import { WebView } from "https://deno.land/x/webview/mod.ts"; 2 3const sharedOptions = { 4 width: 400, 5 height: 200, 6 resizable: true, 7 debug: true, 8 frameless: false, 9}; 10 11const webview1 = new WebView({ 12 title: "Multiple deno_webview example", 13 url: `data:text/html, 14 15 161
17 18 19 `, 20 ...sharedOptions, 21}); 22 23const webview2 = new WebView({ 24 title: "Multiple deno_webview example", 25 url: `data:text/html, 26 27 282
29 30 31 `, 32 ...sharedOptions, 33}); 34 35await Promise.all([webview1.run(), webview2.run()]);

Forever / PM2
Forever 和 PM2是 CLI 工具,可以使给定脚本作为守护程序连续运行。与 Forever 不同,PM2 更完整,还可以用作负载均衡器。两者在 Node.js 中都非常有用,但是我们可以在 Deno 中使用吗?
Forever 仅能用于 Node,不过我们可以借助 PM2 运行非 Node.js 脚本,所以可以将其用于 Deno。

创建一个 app.sh
文件
1#!/bin/bash 2deno run -A myCode.ts
然后
1➜ pm2 start ./app.sh

Express / Koa
Express 和 Koa 是最知名的 Node 框架。他们以其强大的路由系统和 HTTP 辅助器(重定向、缓存等)而闻名。可以在 Deno中使用它们吗?答案是否…但是有一些替代方法。

Http(标准库)
Deno 自己的标准库已经能够满足 Express 或 Koa 提供的许多功能。https://deno.land/std/http/。
1import { ServerRequest } from "https://deno.land/std/http/server.ts"; 2import { getCookies } from "https://deno.land/std/http/cookie.ts"; 3 4let request = new ServerRequest(); 5request.headers = new Headers(); 6request.headers.set("Cookie", "full=of; tasty=chocolate"); 7 8const cookies = getCookies(request); 9console.log("cookies:", cookies);
但是声明路由的方法并没有什么吸引力,所以让我们看看更多的替代方案。
Oak (第三方库)
受 Koa 启发,这是目前最优雅的解决方案之一。
-
https://github.com/oakserver/oak
1import { Application, } from "https://deno.land/x/oak/mod.ts"; 2 3const app = new Application(); 4 5app.use((ctx) => { 6 ctx.response.body = "Hello World!"; 7}); 8 9await app.listen({ port: 8000 });
Abc(第三方库)
类似于 Oak
-
https://deno.land/x/abc。
1import { Application } from "https://deno.land/x/abc/mod.ts"; 2 3const app = new Application(); 4 5app.static("/static", "assets"); 6 7app.get("/hello", (c) => "Hello!") 8 .start({ port: 8080 });
Deno-express(第三方库)
也许是和 Express Framework 最相似的替代方案。
-
https://github.com/NMathar/deno-express。
1import * as exp from "https://raw.githubusercontent.com/NMathar/deno-express/master/mod.ts"; 2 3const port = 3000; 4const app = new exp.App(); 5 6app.use(exp.static_("./public")); 7app.use(exp.bodyParser.json()); 8 9app.get("/api/todos", async (req, res) => { 10 await res.json([{ name: "Buy some milk" }]); 11}); 12 13const server = await app.listen(port); 14console.log(`app listening on port ${server.port}`);
MongoDB
MongoDB 是有着巨大的可扩展性和灵活性的文档型数据库。在 JavaScript 生态中已被广泛使用,使用它的许多技术栈(如 MEAN 或 MERN)都非常受欢迎。

所以可以将 MongoDB 与 Deno 结合使用。可以使用这个驱动程序:
-
https://github.com/manyuanrong/deno_mongo。
1import { init, MongoClient } from "https://deno.land/x/mongo@v0.6.0/mod.ts"; 2 3// Initialize the plugin 4await init(); 5 6const client = new MongoClient(); 7client.connectWithUri("mongodb://localhost:27017"); 8 9const db = client.database("test"); 10const users = db.collection("users"); 11 12// insert 13const insertId = await users.insertOne({ 14 username: "user1", 15 password: "pass1" 16}); 17 18// findOne 19const user1 = await users.findOne({ _id: insertId }); 20 21// find 22const users = await users.find({ username: { $ne: null } }); 23 24// aggregation 25const docs = await users.aggregation([ 26 { $match: { username: "many" } }, 27 { $group: { _id: "$username", total: { $sum: 1 } } } 28]); 29 30// updateOne 31const { matchedCount, modifiedCount, upsertedId } = await users.updateOne( 32 username: { $ne: null }, 33 { $set: { username: "USERNAME" } } 34); 35 36// deleteOne 37const deleteCount = await users.deleteOne({ _id: insertId });
PostgresSQL

像 MongoDB 一样,也有 PostgresSQL 的驱动:https://github.com/buildondata/deno-postgres。
1import { Client } from "https://deno.land/x/postgres/mod.ts"; 2 3const client = new Client({ 4 user: "user", 5 database: "test", 6 hostname: "localhost", 7 port: 5432 8}); 9await client.connect(); 10const result = await client.query("SELECT * FROM people;"); 11console.log(result.rows); 12await client.end();
MySQL / MariaDB

与 MongoDB 和 PostgresSQL 一样,还有 MySQL/MariaDB 的驱动程序。
-
https://github.com/manyuanrong/deno_mysql
1import { Client } from "https://deno.land/x/mysql/mod.ts"; 2 3const client = await new Client().connect({ 4 hostname: "127.0.0.1", 5 username: "root", 6 db: "dbname", 7 poolSize: 3, // connection limit 8 password: "password", 9}); 10 11let result = await client.execute(`INSERT INTO users(name) values(?)`, [ 12 "aralroca", 13]); 14console.log(result); 15// { affectedRows: 1, lastInsertId: 1 }
Redis

Redis 是最著名的缓存数据库,也有 Deno 驱动程序。
-
https://github.com/keroxp/deno-redis
1import { connect } from "https://denopkg.com/keroxp/deno-redis/mod.ts"; 2 3const redis = await connect({ 4 hostname: "127.0.0.1", 5 port: 6379 6}); 7const ok = await redis.set("example", "this is an example"); 8const example = await redis.get("example");
Nodemon

Nodemon 用于在开发环境中用于监视文件中的更改,并自动重新启动服务器。这使 Node 开发更加有趣,而无需手动重启服务器来查看应用的更改。它可以用在 Deno 中吗?
抱歉,不可以…但是有另外一种选择:Denon。
-
https://github.com/eliassjogreen/denon
可以像使用 deno run
一样用 Denon 来执行脚本。
1➜ denon server.ts
Jest, Jasmine, Ava…

在 Node.js 生态中,有许多测试用的工具。但是官方并没有提供测试 Node.js 代码的方法。
在 Deno中,有一种官方的方法,可以用测试标准库。
-
https://deno.land/std/testing
1import { assertStrictEq } from 'https://deno.land/std/testing/asserts.ts' 2 3Deno.test('My first test', async () => { 4 assertStrictEq(true, false) 5})
这样运行测试:
1➜ deno test
Webpack, Parcel, Rollup…

Deno 的一个优势是无需打包器(例如 Webpack、 Parcel 或 Rollup)就可以使 ESmodules 与 TypeScript 在一起工作。
但是如果给定一个文件树,我们是否可以打成一个包,把所有内容放到一个文件中并在网络上运行它呢?
当然可以。可以用 Deno 的 CLI 做到这一点,不需要第三方打包程序。
1➜ deno bundle myLib.ts myLib.bundle.js
然后就可以加载到浏览器中了:
1 2 import * as myLib from "myLib.bundle.js"; 3
Prettier

在过去的几年中,Prettier 在 JavaScript 生态系统中已广为人知,正是因为有它,你不必再去担心格式化文件的麻烦。
实际上它仍然可以在 Deno 上使用,但是这失去了意义,因为 Deno 有自己的格式化程序。
可以用以下命令格式化文件:
1➜ deno fmt
NPM Scripts

在 Deno 中, package.json
不再存在。我很怀念在 package.json
中声明的脚本。
一个简单的解决方案是用 makefile
,并使用 make
命令执行。但是,如果你想念 npm 语法,那么 Deno 有一个 npm 风格的脚本运行器:
-
https://github.com/umbopepato/velociraptor
你可以用脚本去定义文件:
1# scripts.yaml 2scripts: 3 start: deno run --allow-net server.ts 4 test: deno test --allow-net server_test.ts
执行:
1➜ vr run 2
另一种选择是 denox (https://github.com/BentoumiTech/denox) ,与 Velociraptor 非常相似。
Nvm

Nvm (https://github.com/nvm-sh/nvm) 是一个用于管理多个活动 Node 版本的 CLI,可以根据你的项目轻松升级或降级版本。
在 Deno 中 nvm
的替代物是 dvm
。
-
https://github.com/axetroy/dvm
1➜ dvm use 1.0.0
Npx
Npx 近年来非常流行,可以直接调用 npm 包内的模块。由于 Deno 是一个独立的生态,所以不存在 npm 中的那些重多项目。那么我们不用 deno install https://url-of-module.ts
而用 Deno 执行来执行它们呢?
以与运行项目相同的方式,而不是文件,放置模块的 URL:
1➜ deno run https://deno.land/std/examples/welcome.ts
如你所见,我们不仅需要记住模块的名称,还要记住整个 URL,这样用起来很困难。但是另一方面,它提供了更多的灵活性,因为我们可以运行任何文件,而不仅仅是像 npx
这样在 package.json
中指定的文件。
在Docker 中运行

要在 Docker 中运行Deno,可以这样创建 Dockerfile:
1FROM hayd/alpine-deno:1.0.0 2 3EXPOSE 1993 # Port. 4 5WORKDIR /app 6 7USER deno 8 9COPY deps.ts . 10RUN deno cache deps.ts # Cache the deps 11 12ADD . . 13RUN deno cache main.ts # main entrypoint. 14 15CMD ["--allow-net", "main.ts"]
这样构建并运行:
1➜ docker build -t app . && docker run -it --init -p 1993:1993 app
Repo: https://github.com/hayd/deno-docker
用于亚马逊 lambda 运算

要将 Deno 用于 AWS lambda,可以用 Deno STD 库中的模块。
-
https://deno.land/x/lambda。
1import { 2 APIGatewayProxyEvent, 3 APIGatewayProxyResult, 4 Context 5} from "https://deno.land/x/lambda/mod.ts"; 6 7export async function handler( 8 event: APIGatewayProxyEvent, 9 context: Context 10): Promise { 11 return { 12 body: `Welcome to deno ${Deno.version.deno} `, 13 headers: { "content-type": "text/html;charset=utf8" }, 14 statusCode: 200 15 }; 16}
有趣的参考:
-
把 Deno 用在 Vercel 中:https://github.com/lucacasonato/now-deno
-
AWS 中的 Deno:https://blog.begin.com/deno-runtime-support-for-architect-805fcbaa82c3
结束语
我确定肯定会遗漏了一些 Node 主题以及它们对应的 Deno 替代方案,如果你有补充请在下面留言。
探索所有可以用在 Deno 中的库:
-
https://deno.land/std
-
https://deno.land/x
-
https://www.pika.dev/