Deno再尝试:使用Deno编写一个简单的WebAPI
内容提要
作者两年前尝试过Deno,如今再次使用Deno构建活动监测器。文章介绍了Deno.serve处理请求、手动路由、统一响应格式、Deno KV存储数据,以及用Rust编写客户端上报状态,并通过macOS launchd后台运行。最终部署到Deno Deploy,作者认为Deno已成熟,适合小工具和个人项目,但大型生产项目仍需谨慎。
延伸解读
Deno 的模块系统演进
文章提到 Deno 最初采用基于 HTTP 的模块导入,长 URL 使代码杂乱且依赖管理困难。如今 Deno 支持更易用的导入方式,这反映了其生态的成熟。对于开发者而言,这意味着 Deno 在依赖管理上正在向传统 npm 模式靠拢,降低了上手门槛,但具体支持方式(如 npm 兼容或 import maps)需查阅官方文档。
手动路由的适用场景
作者未使用 Web 框架,而是通过解析 pathname 手动实现路由,并用 Map 封装处理函数。这种方式适合接口数量少的小项目,代码简洁且无额外依赖。但对于路由复杂、需要中间件或参数解析的场景,手动路由会变得繁琐,此时引入框架(如 Hono 或 Oak)可能更高效。
Deno KV 的本地与云端差异
Deno KV 在 Deno Deploy 上可直接使用,但本地运行需启用 --unstable-kv 实验特性。这意味着本地开发与云端部署存在环境差异,开发者需注意配置。此外,Deno KV 的键数组设计支持层级组织和范围查询,适合简单持久化需求,但相比传统数据库,其功能可能有限,不适合复杂查询。
launchd 环境变量注意事项
macOS 的 launchd 服务不直接读取 Shell 环境变量,需通过 launchctl setenv 设置。作者在部署 Rust 客户端时遇到此问题,并提供了解决方案。这提醒开发者,在将程序作为后台服务运行时,需显式配置环境变量,否则程序可能因缺少配置而运行失败。
Q&A
Deno.serve 的基本用法是什么?
Deno.serve 接受一个处理函数,该函数接收 Request 对象并返回 Response。例如:const handler = (req) => new Response('Hello'); Deno.serve(handler);
Deno 如何实现路由?
Deno 本身没有内置路由系统,但可以通过解析 URL 的 pathname 手动实现。简单场景下用 if 判断,复杂一点可以将处理函数封装到 Map 或对象中,根据 pathname 匹配调用。
如何统一 Deno Web API 的响应格式?
可以封装一个响应类,统一管理 success、message、data 等字段,并提供 json() 方法返回 JSON 响应,同时设置 CORS 头。这样所有接口都返回统一格式。
Deno KV 是什么?如何使用?
Deno KV 是 Deno 内置的键值存储,可用于持久化数据。使用 Deno.openKv() 打开,通过 kv.set() 和 kv.get() 操作,键为数组,支持层级和范围查询。本地使用需启用 --unstable-kv 实验特性。
如何用 Rust 编写一个定时上报状态的客户端?
使用 Rust 的 tokio 和 reqwest 库,每隔一定时间(如 20 分钟)向指定 API 发送 GET 请求,携带 apikey 头。示例代码中使用了 tokio::time::interval 和 reqwest::Client。
如何将程序作为 macOS 后台服务运行?
使用 launchd 创建 plist 文件,设置 Label、ProgramArguments、RunAtLoad 和 KeepAlive。注意 launchd 不读取 shell 环境变量,需用 launchctl setenv 设置。这样程序异常退出后会被自动拉起。
Deno Deploy 有哪些特点?适合什么场景?
Deno Deploy 提供 Deno 程序部署、KV 存储、定时任务等能力,部署流程简单,速度快。适合小工具、小型 Web API 或个人项目,可以免维护服务器。
作者对 Deno 的总体评价是什么?
作者认为 Deno 相比两年前已成熟不少,标准库完善,开发体验提升。虽然不适合大型生产项目,但对于小工具、小型 Web API 或个人项目已经足够好用,尤其配合 Deno Deploy 和 Deno KV 很方便。