从 v1 到 v2 的迁移指南
¥Migration guide for v1 to v2
H3 版本 2 包含一些行为和 API 更改,你在迁移时需要考虑应用这些更改。
¥H3 version 2 includes some behavior and API changes that you need to consider applying when migrating.
最新 Node.js 和 ESM 版本
¥Latest Node.js and ESM-only
如果你的应用当前正在使用 CommonJS 模块(require 和 module.exports),由于最新 Node.js 版本支持 require(esm),你仍然可以使用 require("h3")。
¥If your application is currently using CommonJS modules (require and module.exports), You can still use require("h3") thanks to require(esm) supported in latest Node.js versions.
¥You can alternatively use other compatible runtimes Bun or Deno.
Web 标准
¥Web Standards
URL、Headers、Request 和 Response)重写。¥!TIP
H3 v2 is rewritten based on web standard primitives (URL, Headers, Request, and Response).使用 Node.js 时,H3 使用兼容层 (💥 srvx),而在其他运行时使用原生 Web 兼容 API。
¥When using Node.js, H3 uses a compatibility layer (💥 srvx) and in other runtimes uses native web compatibility APIs.
只有在 Node.js 运行时运行服务器时才能访问原生 event.node.{req,res}。
¥Access to the native event.node.{req,res} is only available when running server in Node.js runtime.
event.web 已重命名为 event.req(Web 请求 的实例)。
¥event.web is renamed to event.req (instance of web Request).
响应处理
¥Response Handling
如果你之前使用过以下方法,你可以将它们替换为返回文本、JSON、流或 Web Response 的 return 语句(h3 会智能地检测并处理每个方法):
¥If you were previously using methods below, you can replace them with return statements returning a text, JSON, stream, or web Response (h3 smartly detects and handles each):
send(event, value):迁移到return <value>。sendError(event, <error>):迁移到throw createError(<error>)。sendStream(event, <stream>):迁移到return <stream>。sendWebResponse(event, <response>):迁移到return <response>。
其他重命名的发送实用程序需要显式指定 return:
¥Other send utils that are renamed and need explicit return:
sendNoContent(event)/return null:迁移到return noContent(event)。sendIterable(event, <value>):迁移到return iterable(event, <value>)。sendProxy(event, target):迁移到return proxy(event, target)。handleCors(event):检查返回值(布尔值)并在处理后尽早返回return。serveStatic(event, content):确保在之前添加return。sendRedirect(event, location, code):迁移到return redirect(event, location, code)。
H3 和路由
¥H3 and Router
除了
createApp() 和 createRouter(),你可以使用 new H3()。¥!TIP
Router function is now integrated into the H3 core. Instead of
createApp() and createRouter() you can use new H3().任何处理程序都可以返回响应。如果中间件未返回响应,则会尝试下一个处理程序,如果两个处理程序均未返回,则最终返回 404 错误。路由处理程序可以返回或不返回任何响应,在这种情况下,H3 将发送一个简单的 200 代码,其中包含空内容。
¥Any handler can return a response. If middleware don't return a response, next handlers will be tried and finally make a 404 if neither responses. Router handlers can return or not return any response, in this case, H3 will send a simple 200 with empty content.
H3 已迁移到全新的路由匹配引擎 (🌳 rou3)。你可能会遇到匹配模式的轻微(但更直观)行为变化。
¥H3 migrated to a brand new route-matching engine (🌳 rou3). You might experience slight (but more intuitive) behavior changes for matching patterns.
相对于 v1 的其他变化:
¥Other changes from v1:
- 添加
app.use("/path", handler)的中间件仅匹配/path(而不是/path/foo/bar)。为了像以前一样匹配所有子路径,应该将其更新为app.use("/path/**", handler)。 - 每个处理程序接收到的
event.path都将具有完整路径,不会省略前缀。使用withBase(base, handler)实用程序创建带前缀的应用。(例如:withBase("/api", app.handler))。 router.add(path, method: Method | Method[]签名已更改为router.add(method: Method, path)router.use(path, handler)已弃用。改用router.all(path, handler)。app.use(() => handler, { lazy: true })不再受支持。你可以使用app.use(defineLazyEventHandler(() => handler), { lazy: true })。app.use(["/path1", "/path2"], ...)和app.use("/path", [handler1, handler2])不再受支持。请使用多个app.use()调用。app.resolve(path)已移除。
请求正文
¥Request Body
Request 接口的原生 event.req.* 方法替换。¥!TIP
Most of request body utilities can now be replaced with native event.req.* methods which is based on web Request interface.readBody(event) 实用程序将使用 JSON.parse 或 URLSearchParams 解析 Content-Type 为 application/x-www-form-urlencoded 的请求。
¥readBody(event) utility will use JSON.parse or URLSearchParams for parsing requests with application/x-www-form-urlencoded content-type.
- 对于文本:使用 event.req.text()。
- 对于 JSON:使用 event.req.json()。
- 对于表单数据:使用 event.req.formData()。
- 对于流:使用 event.req.body。
行为变更:
¥Behavior changes:
- 如果传入的请求没有 body(例如,是
GET方法),body 工具不会抛出错误,而是返回空值。 - 原生
request.json和readBody不再使用 unjs/destr。你应该始终过滤和清理来自用户的数据,以避免 prototype-poisoning。
Cookie 和标头
¥Cookie and Headers
现在标头值始终为纯 string(不再有 null、undefined、number 或 string[])。
¥Header values are always a plain string now (no null or undefined or number or string[]).
对于 Set-Cookie 标头,你可以使用始终返回字符串数组的 headers.getSetCookie。
¥For the Set-Cookie header, you can use headers.getSetCookie that always returns a string array.
其他弃用内容
¥Other Deprecations
H3 v2 弃用了一些旧版和别名实用程序。
¥H3 v2 deprecated some legacy and aliased utilities.
应用和路由实用程序
¥App and router utils
createApp/createRouter:迁移到new H3()。
错误实用程序
¥Error utils
createError/H3Error:迁移到HTTPErrorisError:迁移到HTTPError.isError
处理程序实用程序
¥Handler utils
eventHandler/defineEventHandler:迁移到defineHandler(你也可以直接使用函数!)。lazyEventHandler:迁移到defineLazyEventHandler。toEventHandler:移除封装器。isEventHandler:(已移除)任何函数都可以作为事件处理程序。useBase:迁移到withBase。defineRequestMiddleware和defineResponseMiddleware已移除。
请求实用程序
¥Request utils
getHeader/getRequestHeader:迁移到event.req.headers.get(name)。getHeaders/getRequestHeaders:迁移到Object.fromEntries(event.req.headers.entries())。getRequestPath:迁移到event.path或event.url。getMethod:迁移到event.method。
响应实用程序
¥Response utils
getResponseHeader/getResponseHeaders:迁移到event.res.headers.get(name)setHeader/setResponseHeader/setHeaders/setResponseHeaders:迁移到event.res.headers.set(name, value)。appendHeader/appendResponseHeader/appendResponseHeaders:迁移到event.res.headers.append(name, value)。removeResponseHeader/clearResponseHeaders:迁移到event.res.headers.delete(name)appendHeaders:迁移到appendResponseHeaders。defaultContentType:迁移到event.res.headers.set("content-type", type)getResponseStatus/getResponseStatusText/setResponseStatus:使用event.res.status和event.res.statusText。
Node.js 实用程序
¥Node.js utils
defineNodeListener:迁移到defineNodeHandler。fromNodeMiddleware:迁移到fromNodeHandler。toNodeListener:迁移到toNodeHandler。createEvent:(已移除):使用 Node.js 适配器 (toNodeHandler(app))。fromNodeRequest:(已移除):使用 Node.js 适配器 (toNodeHandler(app))。promisifyNodeListener(已移除)。callNodeListener:(已移除)。
Web 实用程序
¥Web Utils
fromPlainHandler:(已移除)迁移到 Web API。toPlainHandler:(已移除)迁移到 Web API。fromPlainRequest(已移除)迁移到 Web API 或使用mockEvent工具进行测试。callWithPlainRequest(已移除)迁移到 Web API。fromWebRequest:(已移除)迁移到 Web API。callWithWebRequest:(已移除)。
正文实用程序
¥Body Utils
readRawBody:迁移到event.req.text()或event.req.arrayBuffer()。getBodyStream/getRequestWebStream:迁移到event.req.body。readFormData/readMultipartFormData/readFormDataBody:迁移到event.req.formData()。
其他实用程序
¥Other Utils
isStream:迁移到instanceof ReadableStream。isWebResponse:迁移到instanceof Response。splitCookiesString:从 cookie-es 使用splitSetCookieString。MIMES:(已移除)。
类型导出
¥Type Exports
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.
¥Removed type exports: WebEventContext, NodeEventContext, NodePromisifiedHandler, AppUse, Stack, InputLayer, InputStack, Layer, Matcher, PlainHandler, PlainRequest, PlainResponse, WebHandler.