写点什么

手把手教你从 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:079294

评论 3 条评论

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

高通中国区董事长孟樸:5G与AI的融合正加速企业数字化转型步伐

新消费日报

LeetCode题解:2665. 计数器 II

Lee Chen

数据虚拟化技术揭秘:如何整合多样数据源及其独特优势

Aloudata

数据分析 数据开发 数据集成 数据编织 数据虚拟化技术

前端三件套配合豆包MarsCode 实现钉钉官网动画

豆包MarsCode

程序员 AI 钉钉 开发

SmoothScroll for mac(鼠标增强工具)激活版

Mac相关知识分享

为什么建议不要使用TikTok共享节点?

Ogcloud

TikTok tiktok运营 TikTok养号 tiktok矩阵 tiktok网络

SecureCRT for mac强大的终端 SSH 仿真工具

Mac相关知识分享

GeoAI驱动土地价值重塑!中国地质大学(武汉)&和鲸社区Workshop圆满结束!

ModelWhale

Workshop 地球科学 geoai 遥感数据

万字长文2024最全Go面经汇总

王中阳Go

Go 面经 大厂

Hadoop优化|全面调优攻略 | HDFS、MapReduce、YARN性能提升秘诀 | 专家实战分享!

敏捷调度TASKCTL

hadoop hdfs YARN MapReduce服务

指标平台为业务部门提供实时、准确的数据支持,以助力业务决策

Aloudata

数据分析 指标管理 指标平台 指标开发

【教程】第二章:设计任务管理系统 —— 胸有成竹,步步为营

NocoBase

开源 低代码 教程 无代码

Unlock the Future of Connectivity: Explore Dual-Band Dual-Concurrent (DBDC) Cards for Industrial Applications

wallyslilly

MT7915

Microsoft Remote Desktop Beta for Mac(微软远程连接工具)

Mac相关知识分享

TG机器人链游开发项目:迈向去中心化游戏新时代

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

TikTok直播有什么要求?

Ogcloud

TikTok tiktok运营 tiktok直播 tiktok直播专线 tiktok直播网络

《深入浅出Apache Spark》系列③:Spark SQL解析层优化策略与案例解析

数新网络官方账号

sql 大数据

Termius for mac(终端模拟器/SSH/SFTP客户端)

Mac相关知识分享

Allavsoft for Mac(优秀的视频下载工具)

Mac相关知识分享

Eudic欧路词典 for Mac(英语词典翻译查询工具)

Mac相关知识分享

DeFi 4.0峥嵘初现:主权金融时代的来临

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

Zabbix 和 Prometheus 选型对比

巴辉特

Prometheus zabbix

枫清科技高雪峰:从大模型到行业智能体的智能转型之路

Fabarta

大模型 #人工智能

SmartSVN for Mac(SVN客户端)

Mac相关知识分享

SpringBoot必须掌握的常用注解!

王磊

AE2025视频后期优化处理:After Effects 2025 for mac 激活版

你的猪会飞吗

mac软件下载 Mac破解软件 AE2025破解版

Navicat Premium 15 for Mac强大数据库管理软件

Mac相关知识分享

指标平台帮助企业在业务运营过程中快速定位和解决业务问题

Aloudata

数据仓库 数据分析 指标管理 指标平台 指标开发

数据分散在不同的业务线,如何对全域数据做高效整合和集成?

Aloudata

数据仓库 数据分析 商业分析 noetl

无代码MES是什么?MES系统包含什么功能?

积木链小链

无代码 无代码平台 无代码MES

高性能日志结构化引擎 — GreptimeDB Piepline 设计与实现技术揭秘

Greptime 格睿科技

时序数据库 日志储存 日志引擎

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