release · 

H3 v2 测试版

⚡ H3 v2 测试版已发布 —— 完全基于 web 标准重写,向后兼容,速度比以往更快!
Pooya Parsa

Pooya Parsa

访问新的 H3 指南 快速入门。

H3 起始于 2020 年末,正值边缘工作者(edge workers)兴起之时。结合 H3 + unjs/unenv,我们可以在带有 Node.js 兼容性的工作者环境中运行 Nitro 部署,兼具两者优势!自从 v1.8 起,H3 已经提升了对 web 标准的支持。

不过,H3 仍然主要基于 Node.js API,带有 web 标准的兼容层。当时这是合乎逻辑的选择,因为 Node.js 在 JavaScript 服务器运行时中非常受欢迎。

得益于像 WinterTC 这样持续发展的 web 标准,以及在 DenoBun 和最新的 Node.js 中的运行时支持,生态系统已准备好优先采用 web 标准进行服务器开发。其优势包括:

  • 跨运行时互操作性(Node.js、Deno、Bun、Workers 等)
  • 跨框架兼容性(H3、Hono、Elysia 等)
  • 跨环境兼容性(前后端共享且熟悉的代码)
  • 利用更多运行时原生原语,如 (Request、URL、Headers 等)
  • 更易进行 API 测试

💥 Srvx:通用 Web 服务器 API

一个主要挑战是 Node.js 缺少对 web 标准 HTTP 服务器的内置支持。为了实现 node:http 兼容,需要一个适配器将 Node.js 的 IncomingMessage 转换为 web 的 Request,并通过 Node.js 的 ServerResponse 处理 web 的 Response。我们实现了一个兼容层,桥接接口,并达到原生 node:http 性能的 96.98%(详见基准测试)。

Deno Bun 和边缘工作者等运行时率先采用 web 标准服务器,但由于缺乏足够的规范,它们并未统一接口。那么你如何访问客户端 IP 地址及额外上下文?如何设置服务器端口和 TLS 选项?如何处理 WebSocket 升级?各运行时都创建了自己的 API。

我们创建了 💥 srvx:一个统一的层,在所有环境中均表现一致。兼容 Deno、Bun、Node.js、Service Workers、Edge Workers。

示例
// 根据各运行时的导出条件,动态使用适配器
import { serve } from "srvx";

serve({
  port: 3000,
  // tls: { cert: "server.crt", key: "server.key" }
  fetch(req) {
    // 服务器扩展:req.ip, req.waitUntil(), req.runtime?.{bun,deno,node,cloudflare,...}
    return new Response("👋 你好!");
  },
});
借助 💥 srvx 统一运行时差异,H3 可以保持简洁,专注于 web 标准 API 。

⚡ H3:微型服务器组合器 🎶

我们努力缩小并简化 H3 的功能范围。

import { H3, serve } from "h3";

const app = new H3().get("/", () => "⚡️ Tadaa!");

serve(app, { port: 3000 });

🪶 比羽毛还轻

我们采用了一种新的基准测试方法,着重衡量框架本身引入的开销,而不是网络层。我们的目标是优化所有相关指标,使结果尽可能接近无框架基线。这种方法使 H3 在每个请求的延迟上得到优化提升,并极大缩小了核心包的体积。

测量项H3 v1🚀 H3 v2
请求处理时间Node: 36 µs
Bun: 27 µs
Deno: 7 ms
Node: 7 µs快5倍
Bun: 3 µs快9倍
Deno: 1.2 µs快156倍
包体积最小: 101 kB
最小+gzip: 39.6 kB
最小: 9.1 kB小91%
最小+gzip: 3.6 kB小90%
最小: 5.2 kB / 最小+gzip: 2.1 kBfetchable 处理器)
H3 v2 的性能几乎等同于使用 new URL(req.url).pathname 进行路由的纯 fetch 处理器。换句话说,使用 H3 基本没有性能损耗!
基准测试针对使用 Web Standard 目标的 H3 核心,不包含适配器。主要用于内部优化。详情参见 benchmark 和 Node.js 适配器性能的 srvx benchmarks

✅ 类型化 Web 标准

H3 采用 web 标准 API,如 RequestResponseURLHeaders,不在标准之上引入新约定。

我们发起了一项强类型 Web API 的新计划:✅ fetchdts。已集成到 H3 中,将标准与类型便利性完美结合。

import { defineHandler } from "h3";

const handler = defineHandler(async (event) => {
  // URL 解析
  const { pathname, searchParams } = event.url;

  // 访问请求头(编辑器中试试自动补全!)
  const accept = event.req.headers.get("Accept");

  // 读取请求体
  const bodyStream = await event.req.body;
  const bodyText = await event.req.text();
  const bodyJSON = await event.req.json();
  const bodyFormData = await event.req.formData();

  // 访问运行时特定上下文
  const { deno, bun, node } = event.req.runtime;

  // 准备响应(h3 会智能处理)
  event.res.headers.set("Content-Type", "application/json");

  return { hello: "web" };
});

接下来调用处理器的 .fetch

const response = await handler.fetch("/");

// 🧙 类型化响应: { hello: string; }
const json = await response.json();
你可以直接将事件处理器作为独立、更轻量的 web 处理器使用,无需 H3 核心!

🧩 中间件和插件

H3 现在提供了符合人体工学的、可组合的中间件链式调用方式,基于 next() 函数(灵感来自 Hono middleware 💛)。

同时,我们引入了一种简单而强大的模式,用于扩展 H3 应用,通过可复用的 插件

import { H3 } from "h3";

const app = new H3().use(async (event, next) => {
  // ... 响应前 ...
  const body = await next();
  // ... 响应后 ...
  event.res.headers.append("x-middleware", "works");
  event.waitUntil(sendMetrics(event));
  return body;
});
接收 next 回调是可选的。中间件也可以像 v1 那样编写,不返回响应。

⬆️ 从 版本 1 迁移

我们尽力减少了破坏性变更。大部分工具仍保持向后兼容。

查看迁移指南

🙌 面向所有人的统一 H(TTP) 服务器工具

H3 及相关项目已迁移至专门的 github 组织 和新的 h3.dev 域名(感谢 syntax.fm 和其他赞助商💛的捐赠)。

在 H3 旗帜下,我们维护了若干用于通用 JavaScript 服务器的关键组件。

全部开源,既可与 H3 一起使用,也可独立于 H3,且支持任意 JavaScript 运行时

❤️ 特别感谢

这次发布离不开优秀的贡献者、社区的反馈(Discord)、受 Hono、Elysia 等 web 标准框架的启发,以及使得开源工作成为可能的赞助商

🗺️ v2(稳定版)路线图

接下来:

  • 收集社区反馈。
  • 基于反馈完成 API 更新。
  • 确保生态兼容,并升级支持 Nitro v3。
加入我们的 Discord,分享你的体验和反馈!
访问新的 H3 指南 快速入门。