从 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.

目前 H3 v2 处于测试阶段。你可以尝试使用 nightly 通道。¥!NOTE Currently H3 v2 in beta stage. You can try with nightly channel.
这是一个正在进行的迁移指南,可能会更新。¥!NOTE This is an undergoing migration guide and might be updated.
H3 已全新重写文档。前往全新的 指南 部分了解更多信息!¥!TIP H3 has a brand new documentation rewrite. Head to the new Guide section to learn more!

最新 Node.js 和 ESM 版本

¥Latest Node.js and ESM-only

H3 v2 需要 Node.js >= 20.11(推荐使用最新的 LTS 版本)。¥!TIP H3 v2 requires Node.js >= 20.11 (latest LTS recommended) .

如果你的应用当前正在使用 CommonJS 模块(requiremodule.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.

你也可以使用其他兼容的运行时 BunDeno

¥You can alternatively use other compatible runtimes Bun or Deno.

Web 标准

¥Web Standards

H3 v2 基于 Web 标准原语(URLHeadersRequestResponse)重写。¥!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

你应该始终显式返回响应主体或抛出错误。¥!TIP You should always explicitly return the response body or throw an error.

如果你之前使用过以下方法,你可以将它们替换为返回文本、JSON、流或 Web Responsereturn 语句(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)
Read more in Sending Response.

H3 和路由

¥H3 and Router

路由功能现已集成到 H3 核心中。
除了 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.

Read more in Request Lifecycle.

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) 已移除。
Read more in Routing.
Read more in Middleware.

请求正文

¥Request Body

现在大多数请求体实用程序都可以用基于 Web 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.parseURLSearchParams 解析 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.

行为变更:

¥Behavior changes:

  • 如果传入的请求没有 body(例如,是 GET 方法),body 工具不会抛出错误,而是返回空值。
  • 原生 request.jsonreadBody 不再使用 unjs/destr。你应该始终过滤和清理来自用户的数据,以避免 prototype-poisoning

¥Cookie and Headers

H3 现在所有实用程序都原生使用标准 Web Headers。¥!TIP H3 now natively uses standard web Headers for all utils.

现在标头值始终为纯 string(不再有 nullundefinednumberstring[])。

¥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:迁移到 HTTPError
  • isError:迁移到 HTTPError.isError

处理程序实用程序

¥Handler utils

  • eventHandler/defineEventHandler:迁移到 defineHandler(你也可以直接使用函数!)。
  • lazyEventHandler:迁移到 defineLazyEventHandler
  • toEventHandler:移除封装器。
  • isEventHandler:(已移除)任何函数都可以作为事件处理程序。
  • useBase:迁移到 withBase
  • defineRequestMiddlewaredefineResponseMiddleware 已移除。

请求实用程序

¥Request utils

  • getHeader / getRequestHeader:迁移到 event.req.headers.get(name)
  • getHeaders / getRequestHeaders:迁移到 Object.fromEntries(event.req.headers.entries())
  • getRequestPath:迁移到 event.pathevent.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.statusevent.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

可能会有更多类型更改。¥!NOTE There might be more type changes.
  • App:迁移到 H3
  • AppOptions:迁移到 H3Config
  • _RequestMiddleware:迁移到 RequestMiddleware
  • _ResponseMiddleware:迁移到 ResponseMiddleware
  • NodeListener:迁移到 NodeHandler
  • TypedHeaders:迁移到 RequestHeadersResponseHeaders
  • HTTPHeaderName:迁移到 RequestHeaderNameResponseHeaderName
  • H3Headers:迁移到原生 Headers
  • H3Response:迁移到原生 Response
  • MultiPartData:迁移到原生 FormData
  • RouteNode:迁移到 RouterEntryCreateRouterOptions:迁移到 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.