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