H3 v1 到 v2 迁移:弃用清单

2026-10-30 17:48 更新

8.1 讲了四个核心变化,这一节是逐项的弃用对照表。源文档给出的弃用项很多,按「请求体 / Cookie 与 Headers / 工具函数 / Node 与 Web 适配 / 类型导出」五组归并。每组都是三列:v1 写法 → v2 写法 → 备注。

💡 一个好消息先说在前面:v2 仍然导出所有被弃用的 v1 名称,所以存量代码不会一升级就编译报错——这些名字只是打上了弃用标记,会逐步移除。真正的破坏性来自 8.1 讲的「模型级变化」(send→return、router 合并),而不是这张表。

四个废弃的 H3Event 属性

先列最隐蔽的一类:下面四个属性在 v2 被标记为废弃(未来版本可能移除)。它们现在还能用,但应尽早换成新的取值路径,因为拿到的对象形态已经变了:

v1 属性 v2 取值 备注
event.path event.url.pathname + event.url.search 不再单独返回路径,需自己拼 query
event.method event.req.method 改从标准 Request 读
event.headers event.req.headers 现在是标准 Headers
event.node event.runtime.node 仅 Node 运行时存在,挪了位置

最容易踩的坑是 event.path:v1 只返回路径本身,v2 建议用 event.url.pathname(注意不含 query string)。如果你代码里既用 event.path 又自己另取 query,迁移后直接换成 event.url 上的两个字段,语义更清晰。

一、请求体工具

v2 的原则是「请求体优先用原生 event.req.*」,旧的 read* 包装大多有了标准替代;同时 readBody 不再用 destr 自动反序列化(见 6.2/7.7,这关乎原型污染,必须自己过滤)。

v1 写法 v2 写法 备注
readRawBody(event) event.req.text() / event.req.arrayBuffer() 直接读原始文本或二进制
getBodyStream(event) event.req.body 原生 ReadableStream
getRequestWebStream(event) event.req.body 同上
readFormData(event) event.req.formData() 标准 FormData
readMultipartFormData(event) event.req.formData() 同上,含文件
readFormDataBody(event) event.req.formData() 同上

二、Cookie 与 Headers

v2 全面改用标准 Web Headers:Header 值现在永远是普通 string,不再可能是 null / undefined / number / string[]——这是类型上的破坏性变化,v1 里判断「header 是否存在」时写 if (header) 还能兼容 falsy,v2 里要改成 if (header !== null) 或直接用 headers.has(name)。

Set-Cookie 因为标准 Headers 只留一个字符串,改用 headers.getSetCookie(),它始终返回字符串数组(每个 cookie 一项),多 cookie 场景下比 v1 的拼接字符串好处理得多。

// v1:Set-Cookie 是拼接字符串,要自己拆分
const cookies = getResponseHeader(event, "set-cookie")?.split(", ");

// v2:getSetCookie 直接给数组
const cookies = event.res.headers.getSetCookie();

⚠️ getRequestProtocol(以及 getRequestURL)不再默认信任 x-forwarded-proto 头。 这是安全相关的关键变化:v2 必须显式 opt in 才信任它——getRequestProtocol(event, { xForwardedProto: true })。这与 getRequestHost(xForwardedHost)和 getRequestIP(xForwardedFor)既有的 opt-in 行为一致。只在你确定前面有可信的反向代理或 CDN 时再开,否则客户端可以伪造协议头、绕过你的 HTTPS 强制逻辑。

三、工具函数

这一组最大,再按用途拆成六个子表。

应用与路由工具

v1 写法 v2 写法 备注
createApp / createRouter new H3() 两者合并,见 8.1

错误工具

v1 写法 v2 写法 备注
createError / H3Error HTTPError 统一错误类型
isError(error) HTTPError.isError(error) 改为类型上的静态方法

Handler 工具

v1 写法 v2 写法 备注
eventHandler / defineEventHandler defineHandler(或直接用函数) 命名更短,函数本身即可作 handler
lazyEventHandler defineLazyEventHandler 仅改名字
isEventHandler (已移除) 任意函数都可以是 handler,不再需要判断
useBase withBase 前缀应用工具改名
defineRequestMiddleware / defineResponseMiddleware (已移除) v2 用 (event, next) 中间件或全局钩子替代

请求工具

v1 写法 v2 写法 备注
getHeader(event, name) / getRequestHeader(event, name) event.req.headers.get(name) 直接读标准 Headers
getHeaders(event) / getRequestHeaders(event) Object.fromEntries(event.req.headers.entries()) 全量转对象
getRequestPath(event) event.url.pathname 改用 URL.pathname
getMethod(event) event.req.method 改用标准 Request
getRequestProtocol(event) event.req 取协议 + { xForwardedProto: true } 才信转发头 见本节上方警告

响应工具

v1 写法 v2 写法 备注
getResponseHeader / getResponseHeaders event.res.headers.get(name) 直接读标准 Headers
setHeader / setResponseHeader / setHeaders / setResponseHeaders event.res.headers.set(name, value) 统一到 set
appendHeader / appendResponseHeader / appendResponseHeaders event.res.headers.append(name, value) 统一到 append
removeResponseHeader / clearResponseHeaders event.res.headers.delete(name) 统一到 delete
appendHeaders appendResponseHeaders 别名收敛
defaultContentType event.res.headers.set("content-type", type) 不再有专门函数
getResponseStatus / getResponseStatusText / setResponseStatus event.res.status / event.res.statusText 改用标准 Response 字段

其他工具

v1 写法 v2 写法 备注
createEventStream(event) new EventStream(event) 用 class 构造,见 5.2
isStream(value) value instanceof ReadableStream 不再有判断函数
isWebResponse(value) value instanceof Response 同上
splitCookiesString 用 cookie-es 的 splitSetCookieString 移出核心,转第三方
MIMES (已移除) 不再内置 MIME 映射

四、Node 与 Web 适配

v2 把适配函数统一成「Handler / Request / Response」命名,并移除了一批一次性转换工具(因为它们已被 Web API 原生取代)。

v1 写法 v2 写法 备注
defineNodeListener defineNodeHandler 仅改名字
fromNodeMiddleware fromNodeHandler 仅改名字
toNodeListener toNodeHandler 仅改名字
createEvent(event) (已移除) 改用 Node 适配器 toNodeHandler(app)
fromNodeRequest (已移除) 同上
promisifyNodeListener (已移除) ——
callNodeListener (已移除) ——
fromPlainHandler (已移除) 直接改用 Web API
toPlainHandler (已移除) 直接改用 Web API
fromPlainRequest (已移除) 改用 Web API 或 mockEvent 测试
callWithPlainRequest (已移除) 直接改用 Web API
fromWebRequest (已移除) 直接改用 Web API
callWithWebRequest (已移除) ——

这一组移除项很多,但逻辑很一致:v2 本身就是 Web 标准的,那些"把 H3 事件 ↔ 平台原语"反复转来转去的桥接函数不再需要——你直接操作 Request / Response 即可。唯一保留的适配层是 Node 的 toNodeHandler,因为 Node 生态仍需一个入口。

五、类型导出

类型名几乎全改了,目标是对齐 Web 标准命名。下面是改名映射:

v1 类型 v2 类型 备注
App H3 对齐新实例名
AppOptions H3Config ——
_RequestMiddleware RequestMiddleware 去掉下划线前缀
_ResponseMiddleware ResponseMiddleware 同上
NodeListener NodeHandler 命名对齐
TypedHeaders RequestHeaders / ResponseHeaders 按请求/响应拆开
HTTPHeaderName RequestHeaderName / ResponseHeaderName 同上
H3Headers 原生 Headers 不再有包装类型
H3Response 原生 Response 同上
MultiPartData 原生 FormData 同上
RouteNode RouterEntry 路由条目
CreateRouterOptions RouterOptions ——

已删除(不再导出的)类型:WebEventContext、NodeEventContext、NodePromisifiedHandler、AppUse、Stack、InputLayer、InputStack、Layer、Matcher、PlainHandler、PlainRequest、PlainResponse、WebHandler。

如果你的代码里 import type 了这些名字,升级后 Typescript 会报「找不到名称」——对照上表改名字(或删掉已删除的)即可。

把这五组对照表与 8.1 的四点核心变化合起来,就是 v1→v2 的完整迁移面。下一节(8.3)回到 v2 正式版的官方发布说明,从「为什么值得升级」的角度再梳理一遍。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号