H3 v2 Beta 深度解读:基于 Web 标准完全重写的极简 HTTP 框架
2026/9/17 19:26:31 网站建设 项目流程

H3 v2 Beta 深度解读:基于 Web 标准完全重写的极简 HTTP 框架

【免费下载链接】h3⚡️ Minimal H(TTP) framework built for high performance and portability项目地址: https://gitcode.com/GitHub_Trending/h31/h3

H3 v2 beta 是 H3(当前仓库 package.json 中版本为2.0.1-rc.28)的一次里程碑式重构:它彻底抛弃了以 Node.js API 为核心、以兼容层适配 Web 标准的旧架构,转而完全基于 Request、src/handler.ts、src/middleware.ts 等)深入剖析其设计动机、性能成果、类型系统、中间件/插件模型与迁移路径,读完你将掌握 H3 v2 的核心 API 与底层实现原理。

为什么需要 v2:边缘计算时代下的 Web 标准觉醒

H3 诞生于 2020 年底边缘 Worker 兴起之时。当时 H3 与 unjs/unenv 搭配,让 Nitro 部署可以在 Worker 环境中运行 Node.js 兼容代码。自 v1.8(详见 v1.8 发布说明,该版本引入了toWebHandler/toPlainHandler适配器与 Web Streams 支持)之后,H3 对 Web 标准的支持持续增强,但本质上仍然是以Node.js API 为第一公民、Web 标准为兼容层——这在 Node.js 主导 JavaScript 服务端运行时生态的年代是合理选择。

如今情况已截然不同:WinterTC 等组织推动的 Web 标准演进,加上 Deno、Bun、以及最新 Node.js 对 Web 标准的原生支持,使得"服务端开发一等公民就是 Web 标准"成为可能。v2 的重写带来的收益包括:

  • 跨运行时互操作:同一套代码在 Node.js、Deno、Bun、Cloudflare Workers 等环境行为一致;
  • 跨框架兼容:H3、Hono、Elysia 等基于 Web 标准的框架可以共享模式与心智模型;
  • 跨环境代码复用:前端与后端共享熟悉且一致的 API;
  • 充分利用运行时原生原语RequestURLHeaders等无需垫片;
  • 更轻松的 API 测试handler.fetch()直接构造Request、返回Response,测试无需启动真实服务器。

srvx:弥合 Node.js 与 Web 标准之间最后一道鸿沟

v2 重写面临的最大挑战是:Node.js 自身没有内置 Web 标准的 HTTP 服务器接口node:http需要一层适配器,将 Node.js 的IncomingMessage桥接为 WebRequest,并把 WebResponse通过 Node.jsServerResponse写出。官方为此实现了一个兼容层(srvx),官方基准数据显示该兼容层可达到原生node:http性能的 96.98%(数据源自官方 srvx 基准,仓库内可参考 test/bench/bench.ts 的同类测量方法论)。

Deno、Bun 与边缘 Worker 率先采纳了 Web 标准,但由于当时缺乏足够完善的规范,各运行时对扩展能力(客户端 IP、服务器端口与 TLS 配置、WebSocket 升级等)各自为政、接口不一。srvx 正是为此诞生的统一层:在 Deno、Bun、Node.js、Service Workers、边缘 Workers 上以完全相同的方式工作,同时提供运行时特有的扩展上下文。

// 根据各运行时 export conditions 自动选择动态适配器 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("👋 Hello there!"); }, });

从仓库源码可以印证这一设计:H3Event通过req.runtime暴露运行时特有上下文(见 src/event.ts 的runtimegetter),并转发waitUntil()调用;package.json 的exports字段为denobunworkerdbrowsernodegeneric分别映射了不同的入口文件(见 src/_entries/ 下的deno.tsbun.tscloudflare.tsservice-worker.tsnode.tsgeneric.ts),这正是"按运行时自动选择适配器"的落地实现。

[!TIP] 有了 srvx 统一运行时差异,H3 可以保持精简,专注于纯 Web 标准 API——这是 v2 架构的核心分工。

H3 v2:Tiny Server Composer

v2 对 H3 自身的作用域做了大量精简,聚焦于核心能力:

  • 🪶 为性能深度优化,比羽毛更轻(见下节基准数据);
  • 👌 直观的类型化 handler、响应与错误处理;
  • 🧩 可复用的中间件与插件;
  • 🌳 高速路由;
  • ➕ 内置工具函数;
  • ❤️ 基于 Web 标准的最大化兼容性(mount嵌套应用等)。

v2 的核心 API 变化是:路由功能直接集成进 H3 核心。不再需要createApp()+createRouter()两件套,而是直接:

import { H3, serve } from "h3"; const app = new H3().get("/", () => "⚡️ Tadaa!"); serve(app, { port: 3000 });

从源码看,src/h3.ts 中的H3类继承自H3CoreH3Core负责请求分发主流程(fetch()~request()handler()toResponse()),而H3在构造时通过createRouter()(来自 rou3 路由引擎)初始化路由表。源码中还通过原型链动态为GETPOSTPUTDELETEPATCHHEADOPTIONSCONNECTTRACEQUERY全部十个方法生成app.get()app.post()等便捷方法。app.all()则注册任意方法均可匹配的路由。

性能层面还有一处值得注意的源码细节:createDispatcher(见 src/h3.ts)会预组合中间件链——首次请求或调用use()/mount()后构建一次composeMiddleware结果并缓存,后续请求直接复用,避免每个请求都重复组合开销;路由中间件与 handler 也在注册时通过composeHandler一次性组合。这正是 v2"接近零成本"性能设计的一部分。

更轻:以框架自身开销为基准的测量方法

v2 采用了全新的基准测试方法:不测量网络层,而是测量框架本身引入的开销,目标是把所有相关指标优化到"没有框架时的基线"水平。官方发布数据如下:

测量项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 倍
打包体积min: 101 kB
min+gzip: 39.6 kB
min:9.1 kB减小 91%
min+gzip:3.6 kB减小 90%
fetch 型 handler 可低至 min:5.2 kB/ min+gzip:2.1 kB

[!TIP] v2 处理请求的性能已与"纯fetchhandler +new URL(req.url).pathname做路由"几乎一致——换句话说,使用 H3 的功能几乎零性能成本。

[!NOTE] 以上数据源自官方发布说明,适用于 Web 标准目标的 H3 核心,不含适配器,主要用于官方内部优化参考。仓库内对应基准测试位于 test/bench 目录(bench.tsbench.test.ts等),其中bench:nodebench:bun脚本(见 package.json)可用于复现核心开销测量。

体积的大幅缩减,与 v2 "只依赖 rou3 + srvx 两个最小依赖"(见 package.json dependencies)以及基于 Web 标准重写密不可分——不再需要庞大的 Node.js 兼容垫片。

类型化 Web 标准:fetchdts 与 defineHandler

v2 全面采用RequestResponseURLHeaders等 Web 标准 API,不再在标准之上发明新的约定。同时,官方发起了一个强类型化 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" }; });

defineHandler定义出的 handler 自带.fetch方法(源码见 src/handler.ts 的handlerWithFetch:它接受字符串、URLRequest作为输入,构造H3Event后经toResponse归一化为Response),可以直接以"函数式 Web handler"的身份独立使用:

const response = await handler.fetch("/"); // 🧙 类型化响应:{ hello: string; } const json = await response.json();

[!TIP] handler 可以脱离 H3 核心独立使用——即使不引入完整框架,defineHandler产出的也是一个更小的、可直接调用的 Web handler。

从源码角度,defineHandler有函数与对象两种重载(见 src/handler.ts),对象形式还支持middleware数组与fetch属性;defineValidatedHandler则在此基础上增加了基于 Standard Schema 的body/headers/query校验(实验性 API)。H3Event(src/event.ts)同时暴露event.req(WebRequest)、event.url(解析后的URL)、event.contextevent.res(惰性创建的响应头容器)与event.waitUntil()。值得注意的是 v1 的event.node.{req,res}在 v2 中已标记为废弃,改为通过event.runtime.node访问(源码注释可佐证)。

中间件与插件:next() 链式模型 + definePlugin 扩展

v2 引入了类似 Hono 的next()链式中间件模型,同时提供了definePlugin这一简单而强大的应用扩展模式。

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; });
import { defineHandler, basicAuth } from "h3"; export default defineHandler({ middleware: [basicAuth({ password: "test" })], handler: (event) => `Hello ${event.context.basicAuth?.username}!`, });
import { H3, onRequest } from "h3"; const app = new H3().use( onRequest((event) => { console.log(`Request: [${event.req.method}] ${event.url.pathname}`); }), );
import { H3, onResponse } from "h3"; const app = new H3().use( onResponse((response, event) => { console.log(`Response: [${event.req.method}] ${event.url.pathname}`, body); }), );
import { H3, onError } from "h3"; const app = new H3().use( onError((error, event) => { console.error(`[${event.req.method}] ${event.url.pathname} !! ${error.message}`); }), );
import { H3, serve, definePlugin } from "h3"; const logger = definePlugin((h3, _options) => { if (h3.config.debug) { h3.use((req) => { console.log(`[${req.method}] ${req.url}`); }); } }); const app = new H3({ debug: true }).register(logger()).all("/**", () => "Hello!");

[!NOTE] 接受next回调是可选的。中间件也可以像 v1 一样不返回响应;若未返回响应,框架会自动继续调用后续中间件与路由 handler(最终没有响应则返回 404)。

源码层面的实现细节值得展开:

  • 预组合中间件链:src/middleware.ts 的composeMiddleware把中间件数组预组合为单一可调用链(ComposedMiddleware),逐层分发成本在建链时一次性支付,请求期间不再重复计算;composeHandler则把"中间件 + 固定 handler"组合为一个EventHandler。路由级中间件在注册时即与路由 handler 组合并缓存。
  • next() 幂等callLayernext闭包保证同一层只触发一次下游,且对返回undefinedkNotFound的中间件自动透传继续(isUnhandledResponse判断),这就是"不返回响应就继续"语义的实现。
  • 中间件匹配器normalizeMiddleware支持routemethodmatch三种过滤选项(见 src/middleware.ts 的createMatcher),底层复用与路由相同的 rou3 匹配引擎与normalizeRoute归一化,确保"路由能命中的请求,守卫也一定覆盖";且 GET 作用域的中间件同样匹配 HEAD 请求(RFC 9110 语义)。
  • onRequest/onResponse/onError:src/utils/middleware.ts 中三者都是基于Middleware的便捷封装;onErrorHTTPError渲染前后介入错误处理,onResponse是终结性的副作用钩子(异常被吸收并记录,不影响已构建的响应,见 src/response.ts)。
  • definePlugin:src/plugin.ts 中definePlugin返回一个工厂函数,调用后得到(h3) => void形式的插件,可在构造时通过config.plugins数组或运行时通过app.register()注入(见 src/h3.ts 构造函数与register方法)。上例中app.register(logger())即按debug配置决定是否注册日志中间件。
  • basicAuth 的安全性:仓库中的 src/utils/auth.ts 实现了完整的 RFC 7617/9110 兼容认证:支持username/password或自定义validate函数、realm配置(默认"auth")、统一随机抖动(randomJitter)防止时序侧信道、恒定时间比较(timingSafeEqual),并以401+WWW-Authenticate挑战头拒绝非法凭据。

从 v1 迁移:最小化破坏性变更

v2 致力于将破坏性变更降到最低,大部分工具函数保持了向后兼容。完整迁移指南见 docs/5.migration/0.index.md,要点包括:

  • 运行时要求:v2 仅支持 ESM,要求 Node.js >= 20.11(最新 LTS 推荐),也可运行于 Bun、Deno;require("h3")在新版 Node.js 中仍可用(require(esm)支持)。
  • Web 标准访问event.web更名为event.req(WebRequest实例);event.node.{req,res}仅在 Node.js 运行时可用,且推荐改用event.runtime.node
  • 响应处理:始终坚持显式return响应体或throw错误。v1 的send()sendError()sendStream()sendWebResponse()分别迁移为return <value>throw createError(<error>)return <stream>return <response>sendNoContentreturn noContent()sendIterablereturn iterable(...)sendProxyreturn proxy(...)sendRedirectreturn redirect(location, code)等(见 迁移指南 完整清单)。
  • 应用与路由合并createApp()+createRouter()合并为new H3();路由匹配引擎迁移到 rou3,个别匹配行为有更直觉的变化。app.use("/path", handler)现在只匹配/path本身,匹配子路径需写成app.use("/path/**", handler)
  • 请求体读取readBody(event)仍可用(按 content-type 走JSON.parseURLSearchParams),但文本/JSON/表单/流分别可用原生的event.req.text()event.req.json()event.req.formData()event.req.body替代(完整迁移指南见 docs/5.migration/0.index.md)。

统一的 H(TTP) 服务端工具生态

v2 发布后,H3 及其关联项目迁移至统一的 h3js 组织,并启用了新的 h3.dev 域名。在 H3 这一框架伞下,官方维护着多个面向"通用 JavaScript 服务器"的关键组件,全部开源、可独立或搭配 H3 使用,且支持任意 JavaScript 运行时

  • ⚡️h3:极简 HTTP 框架(即本仓库);
  • 🌳rou3:轻量级 JavaScript 路由器(H3 的依赖,见 package.json);
  • 💥srvx:通用 Web 服务器 API(H3 的依赖,负责跨运行时适配);
  • 🔌crossws:跨平台 WebSocket 支持(H3 的可选 peer dependency,见 package.json)。

通往 v2 稳定版的路由图

v2 beta 之后的下一步计划包括:

  • 收集社区反馈;
  • 基于反馈定稿 API;
  • 确保生态兼容,并完成 Nitro v3 的升级适配。

如果你在实战中遇到问题,可优先参考本仓库的 基础指南、工具函数文档 与 示例代码 目录(其中 middleware.mjs、router.mjs、handler-fetch.mjs、plugin.mjs 等文件与本文所述 v2 特性一一对应),以验证 API 的实际用法。

【免费下载链接】h3⚡️ Minimal H(TTP) framework built for high performance and portability项目地址: https://gitcode.com/GitHub_Trending/h31/h3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询