写点什么

手把手教你从 Node 快速迁移到 Deno

  • 2020-06-03
  • 本文字数:4903 字

    阅读完需:约 16 分钟

手把手教你从Node快速迁移到Deno

上周我发表了一篇文章,介绍了 Deno 以及如何使用 Deno 和 Preact 创建一个聊天应用。文章发布后收到了很多询问,大多数问题关心的是:如何使用新的 Deno 生态系统来做那些我们原来用 Node 做的事情。我试着收集了一些 Node 中最常用的主题,并找出了它们在 Deno 中的替代方案。

首先我想明确一点,在 Deno 中我们可以使用许多现有的 Node.js 模块。由于许多模块都是可重用的,因此用不着为所有的事情都寻找替代选项。你可以访问 pika.dev 查找可以在 Deno 中使用的模块。


本文最初发布于 Aral Roca 个人网站,经原作者授权由 InfoQ 中文站翻译并分享。

Electron

在 Node.js 中,我们可以使用 Electron 创建桌面应用程序。Electron 使用 Chromium 作为界面来运行 Web 环境。但是,我们可以在 Deno 中使用 Electron 吗?或者有其他选择吗?



现在,Electron 是完全不能用在 Deno 下的,我们必须寻找替代方案。由于 Deno 是用 Rust 开发的,因此我们可以使用 web-view rust bindings 在 Deno 中运行桌面应用程序。


这样,我们就可以使用原生 OS webview 来运行任意数量的 Web 视图了。


仓库:


https://github.com/eliassjogreen/deno_webview


import { WebView } from "https://deno.land/x/webview/mod.ts";
const sharedOptions = { width: 400, height: 200, resizable: true, debug: true, frameless: false,};
const webview1 = new WebView({ title: "Multiple deno_webview example", url: `data:text/html, <html> <body> <h1>1</h1> </body> </html> `, ...sharedOptions,});
const webview2 = new WebView({ title: "Multiple deno_webview example", url: `data:text/html, <html> <body> <h1>2</h1> </body> </html> `, ...sharedOptions,});
await Promise.all([webview1.run(), webview2.run()]);
复制代码


Forever/PM2

Forever 和 PM2 是用来确保作为守护程序的指定脚本可以持续运行的 CLI 工具。与 Forever 不同,PM2 功能更完善,还可以用作负载均衡器。两者在 Node 中都很好用,但是我们可以在 Deno 中使用它们吗?


Forever 只适用于 Node,因此在 Deno 中是用不了的。但我们可以使用 PM2 运行非 Node 脚本,因此可以将其用于 Deno。



创建一个 app.sh 文件


#!/bin/bashdeno run -A myCode.ts
复制代码


然后


➜ pm2 <span>start</span> ./app.sh
复制代码


Express/Koa

Express 和 Koa 都是最出名的 Node 框架。它们拥有强大的路由系统和 HTTP helpers(重定向,缓存等),因而广受欢迎。我们可以在 Deno 中使用它们吗?答案是否定的,但是也有一些替代方法。



Http(标准库)Deno 自己的标准库就能提供 Express 或 Koa 提供的许多功能了:


https://deno.land/std/http/


import { ServerRequest } from "https://deno.land/std/http/server.ts";import { getCookies } from "https://deno.land/std/http/cookie.ts";
let request = new ServerRequest();request.headers = new Headers();request.headers.set("Cookie", "full=of; tasty=chocolate");
const cookies = getCookies(request);console.log("cookies:", cookies);
复制代码


但是,它声明路由的方法看起来不怎么好用,因此我们来看看更多替代方案。

Oak(第三方库)

受 Koa 启发的 Oak 是目前最优雅的解决方案之一:https://github.com/oakserver/oak


import { Application,  } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((ctx) => { ctx.response.body = "Hello World!";});
await app.listen({ port: 8000 });
复制代码

Abc(第三方库)

类似 Oak:https://deno.land/x/abc


import { Application } from "https://deno.land/x/abc/mod.ts";
const app = new Application();
app.static("/static", "assets");
app.get("/hello", (c) => "Hello!") .start({ port: 8080 });
复制代码

Deno-Express(第三方库)

也许是最接近 Express 框架的替代方案:https://github.com/NMathar/deno-express


import * as exp from "https://raw.githubusercontent.com/NMathar/deno-express/master/mod.ts";
const port = 3000;const app = new exp.App();
app.use(exp.static_("./public"));app.use(exp.bodyParser.json());
app.get("/api/todos", async (req, res) => { await res.json([{ name: "Buy some milk" }]);});
const server = await app.listen(port);console.log(`app listening on port ${server.port}`);
复制代码

MongoDB

MongoDB 是一个拥有强大可扩展性和灵活性的文档数据库。它在 JavaScript 生态系统中应用广泛,很多技术栈(如 MEAN 或 MERN)都会使用它,因此它非常受欢迎。



我们可以将 MongoDB 用在 Deno 生态中,可以使用以下驱动程序:https://github.com/manyuanrong/deno_mongo


import { init, MongoClient } from "https://deno.land/x/mongo@v0.6.0/mod.ts";
// Initialize the pluginawait init();
const client = new MongoClient();client.connectWithUri("mongodb://localhost:27017");
const db = client.database("test");const users = db.collection("users");
// insertconst insertId = await users.insertOne({ username: "user1", password: "pass1"});
// findOneconst user1 = await users.findOne({ _id: insertId });
// findconst users = await users.find({ username: { $ne: null } });
// aggregationconst docs = await users.aggregation([ { $match: { username: "many" } }, { $group: { _id: "$username", total: { $sum: 1 } } }]);
// updateOneconst { matchedCount, modifiedCount, upsertedId } = await users.updateOne( username: { $ne: null }, { $set: { username: "USERNAME" } });
// deleteOneconst deleteCount = await users.deleteOne({ _id: insertId });
复制代码

PostgreSQL


与 MongoDB 一样,PostgresSQL 也有一个驱动程序:


https://github.com/buildondata/deno-postgres


import { Client } from "https://deno.land/x/postgres/mod.ts";
const client = new Client({ user: "user", database: "test", hostname: "localhost", port: 5432});await client.connect();const result = await client.query("SELECT * FROM people;");console.log(result.rows);await client.end();
复制代码

MySQL/MariaDB


与 MongoDB 和 PostgresSQL 一样,MySQL/MariaDB 也有一个驱动程序:


https://github.com/manyuanrong/deno_mysql


import { Client } from "https://deno.land/x/mysql/mod.ts";
const client = await new Client().connect({ hostname: "127.0.0.1", username: "root", db: "dbname", poolSize: 3, // connection limit password: "password",});
let result = await client.execute(`INSERT INTO users(name) values(?)`, [ "aralroca",]);console.log(result);// { affectedRows: 1, lastInsertId: 1 }
复制代码

Redis


Redis 是最出名的缓存数据库,它也有 Deno 的驱动程序:


https://github.com/keroxp/deno-redis


import { connect } from "https://denopkg.com/keroxp/deno-redis/mod.ts";
const redis = await connect({ hostname: "127.0.0.1", port: 6379});const ok = await redis.set("example", "this is an example");const example = await redis.get("example");
复制代码

Nodemon


Nodemon 被用来在开发环境中监视文件的任何更改,发现更改后会自动重新启动服务器。它显著提升了 Node 的开发体验,开发人员无需再手动停止和重启服务器以查看应用更改。它可以在 Deno 中使用吗?


抱歉,你不能,但是也有另一种选择:Denon,Denon 的用法和使用 deno run 执行脚本一样。


https://github.com/eliassjogreen/denon


➜ denon server.<span>ts</span>
复制代码

Jest、Jasmine、Ava……


在 Node.js 生态系统中,测试运行器有很多选项可用。但官方并没有提供一种测试 Node.js 代码的方法。


在 Deno 中有一种官方方法,你可以使用 testing 标准库:


https://deno.land/std/testing


import { assertStrictEq } from 'https://deno.land/std/testing/asserts.ts'
Deno.test('My first test', async () => { assertStrictEq(true, false)})
复制代码


要运行测试:


➜ deno <span>test</span>
复制代码

Webpack、Parcel、Rollup……


Deno 的优势之一是我们可以搭配使用 ES 模块与 TypeScript,而无需诸如 Webpack、Parcel 或 Rollup 之类的打包器。


但你可能想要知道:如果给定了一棵文件树,我们是否可以制作一个包,将所有内容放到一个文件中以在 Web 环境中运行呢?


答案是肯定的。我们可以使用 Deno 的 CLI 做到这一点。这样就无需第三方打包器了。


➜ deno bundle myLib.ts myLib.bundle.js
复制代码


现在可以将其加载到浏览器中:


<script type="module">  import * as myLib from "myLib.bundle.js";</script>
复制代码

Prettier


在过去的几年中,Prettier 在 JavaScript 生态系统中大受欢迎,因为有了它,你就不用再操心格式化文件的事情了。


其实它也能用在 Deno 上,但这没什么意义,因为 Deno 有自己的格式化程序。


你可以使用以下命令格式化文件:


➜ deno fmt

NPM Scripts


在 Deno 中,package.json 不复存在。而我非常想念的一个特性是在 package.json 中声明的脚本。


一个简单的解决方案是使用一个 makefile,并用 make 执行它。但如果你怀念 npm 语法,那么 Deno 也有一个 npm 样式的脚本运行器:


https://github.com/umbopepato/velociraptor


你可以使用脚本定义文件:


# scripts.yamlscripts:  start: deno run --allow-net server.ts  test: deno test --allow-net server_test.ts
复制代码


这样执行:


➜ vr run <SCRIPT>
复制代码


另一个替代品是 denox,与 Velociraptor 非常相似。

Nvm


Nvm 是一个 CLI,用来管理多个活动 Node 版本,以便根据项目需求轻松升级或降级版本。


在 Deno 中 nvm 的等效方案是 dvm:


https://github.com/axetroy/dvm


➜ dvm use 1.0.0
复制代码

Npx

近年来 Npx 非常流行,因为它可以直接执行 npm 软件包,而无需安装它们。现在,由于 Deno 是一个独立的生态系统,所以 npm 中的许多项目都不可用了。那么,我们能不能不用 deno install https://url-of-module.ts 安装 Deno 模块,就直接使用它们呢?


答案是可以的,就和我们运行项目的方法一样,只不过用的是模块而非文件的 URL:


➜  deno run https://deno.land/std/examples/welcome.ts
复制代码


如你所见,我们不仅需要记住模块的名称,而且还要记住整个 URL,所以用起来很麻烦。另一方面,它提供了更大的灵活性,因为我们可以运行任何文件,而不仅仅是在 package.json 中指定为二进制文件的文件(如 npx)。

在 Docker 上运行


要在 Docker 内部运行 Deno,我们可以创建以下 Dockerfile:


FROM hayd/alpine-deno:1.0.0
EXPOSE 1993 # Port.
WORKDIR /app
USER deno
COPY deps.ts .RUN deno cache deps.ts # Cache the deps
ADD . .RUN deno cache main.ts # main entrypoint.
CMD ["--allow-net", "main.ts"]
复制代码


构建 + 运行:


➜  docker build -t app . && docker run -it --init -p 1993:1993 app
复制代码


仓库:https://github.com/hayd/deno-docker

作为 lambda 运行


要将 Deno 用作一个 lambda,可以使用 Deno 标准库中的这个模块:


https://deno.land/x/lambda


import {  APIGatewayProxyEvent,  APIGatewayProxyResult,  Context} from "https://deno.land/x/lambda/mod.ts";
export async function handler( event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> { return { body: `Welcome to deno ${Deno.version.deno} 🦕`, headers: { "content-type": "text/html;charset=utf8" }, statusCode: 200 };}
复制代码


有趣的参考:


总结

我肯定遗漏了一些 Node 主题以及它们的 Deno 替代方案,大家有兴趣的话可以在评论里补充。我希望本文能帮助你跨过 Deno 的入门门槛。


想要了解可以用在 Deno 中的所有库:



原文链接:


https://aralroca.com/blog/from-node-to-deno


2020-06-03 18:079717

评论 3 条评论

发布
用户头像
作者 Aral Roca 感谢译者
2020-06-09 03:17
回复
用户头像
各种标题党 一股头条自媒体的味道
2020-06-04 11:19
回复
用户头像
这叫快速迁移?明明是重写好吗
2020-06-04 09:06
回复
没有更多了
发现更多内容

【推荐】贵阳市等保测评机构看这里!

行云管家

贵阳 等保 等级保护 等保测评

SUFS: 存储资源使用量预测服务

KaiwuDB

KaiwuDB 存储资源使用量预测

字节跳动开源 Kelemetry:面向 Kubernetes 控制面的全局追踪系统

字节跳动开源

Kubernetes 云原生 可观测 追踪系统

架构师日记-到底该如何搭建一个新系统 | 京东云技术团队

京东科技开发者

架构 架构设计 工程架构 企业号 7 月 PK 榜

手把手教你用 NebulaGraph AI 全家桶跑图算法

NebulaGraph

人工智能 图数据库

实时社群技术专题(二):百万级成员实时社群技术实现(消息系统篇)

JackJiang

网络编程 即时通讯 IM

掌握这些写简历投简历的“黑魔法”,告别简历已读不回!

王中阳Go

golang 简历优化 面试技巧 求职面试 后端面试

龙蜥开发者说:参与开源要敢于担任不同角色 | 第 21 期

OpenAnolis小助手

开源 标准化 sig 龙蜥开发者说 T-one

用友BIP数智化底座使能行业创新发展

用友BIP

数智底座

MobPush 工作台操作指南:查看推送数据

MobTech袤博科技

大数据 前端 后端

和鲸 × 于峻川丨以遥感领域为例,浅谈 AI for Science 带来的数据开放、跨学科协同及产学研一体

ModelWhale

遥感 AI for Science 协同科研 数据开放 产学研一体

性能测试的理解误区

老张

性能测试 稳定性保障

经过半年的努力,我终于成为了谷歌开发者专家(GDE)

拭心

android 面试 谷歌 GDE

sharding-jdbc分库连接数优化 | 京东物流技术团队

京东科技开发者

分库分表 Sharding sharding-jdbc 企业号 7 月 PK 榜

【活动回顾】Data + AI 时代下的云数仓设计 @Qcon

Databend

浅析JVM GC配置指南 | 京东云技术团队

京东科技开发者

JVM 垃圾回收 GC 企业号 7 月 PK 榜

我们搬家啦!新家园,新征程,新篇章

KaiwuDB

KaiwuDB 剪彩 揭牌

小红书2024届REDstar技术提前批招聘火热进行中,快喊上学弟学妹看过来!【附专属内推码】

小红书技术REDtech

技术 招聘 校招 小红书

谈一谈LLM在推荐域的一些理解

阿里技术

大模型 AIGC

壹米滴答助力制造业、商贸业及电商企业提升商业流通效率

联营汇聚

极客欢聚,燃动夏日!开发者嘉年华等你来

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨

DHorse v1.2.1 发布,基于k8s的发布平台

tiandizhiguai

DevOps k8s

常规LED广告显示屏的运营成本怎么估算

Dylan

广告 项目 运营 成本 LED显示屏

Python第三方库(包)的安装(windows系统)

MEImei

纯代码和低代码的本质区别

互联网工科生

软件开发 低代码 代码开发

中字头企业数字化转型的挑战与机遇

用友BIP

国产替代

手把手教你从Node快速迁移到Deno_开源_Aral Roca_InfoQ精选文章