H3 是一个多功能的 H(TTP) 框架,采用 TypeScript 编写,目前为 Nitro 和 Nuxt 提供支持。
近两年前,我们创建了 H3,旨在成为 Nuxt 3 最轻量的 HTTP 框架,确保与 Node.js 兼容并提供优雅的开发体验。它还致力于拥有未来主义的设计,能够适应 Edge 和 Web Worker 运行时,这在当时是一个相对较新的概念。
同期,我们还开发了 unjs/unenv,这是一个轻量层,无需 Node.js 即可让 Edge 兼容运行时使用 Node.js 库和 HTTP 中间件。这项创新在帮助我们利用 NPM 和 Node.js 生态系统的强大功能方面发挥了关键作用,而无需从头开始为 Web 兼容性构建一切。H3 和 unenv 的协同组合最终使 Nitro 成为完全兼容 Edge 运行时的开创性 Web 框架之一。
此次最新发布使 H3 更接近于开箱即用地提供原生 Web API 兼容性。
🚀 此版本已立即向包括 Nitro 和 Nuxt 3 在内的所有生态系统软件包开放。请记住刷新您的
lockfile
和node_modules
以接收更新。
Web 和 Plain 适配器
我们引入了一个新的内置适配器,它具有与 fetch 兼容的签名,以 Request 作为输入,以 Response 作为返回值。
这意味着您现在可以将 H3 应用程序无缝部署到诸如 Cloudflare Workers、Deno Deploy、Bun 和 Lagon 等运行时上。
有关实际示例和演示,请查看 h3-on-edge 仓库。
// import { createApp, eventHandler, toWebHandler } from 'h3'
import { createApp, eventHandler, toWebHandler } from 'https://esm.sh/[email protected]'
const app = createApp()
app.use(
'/',
eventHandler(event => 'H3 works on edge!'),
)
const webHandler = toWebHandler(app) // (Request) => Promise<Response>
除了 Web 处理程序,我们还引入了一种新的 plain 适配器格式,使用 toPlainHandler(app)
语法。这有助于 H3 与任何使用 plain 输入和响应对象的无服务器平台无缝集成。
所有这些都得益于新流式传输功能的实现以及 unjs/unenv(它提供了轻量级的 Node.js 兼容层)。此前,这种级别的集成只能通过 Nitro presets 来实现。
此外,我们还引入了一系列新的 Web 助手函数
toWebRequest(event)
:将 H3 事件对象转换为 Web Request。getRequestWebStream(event)
:从当前 H3 事件请求中获取可读流。fromPlainHandler(plainHandler)
:将 plain 对象处理程序转换为 H3 兼容的事件处理程序。fromWebHandler(webHandler)
:将 Web Request/Response 处理程序转换为 H3 兼容的事件处理程序。
Web Streams 支持
H3 现在支持原生 Readable Stream 响应。这本身就带来了与 Vercel/AI 等库的兼容性,这些库依赖于流式响应(demo)。
利用此功能非常简单——只需从您的事件处理程序返回一个 Readable Stream 或 Response 对象。
export default defineEventHandler((event) => {
setResponseHeader(event, 'Content-Type', 'text/html')
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
for (const token of 'Streaming is so cool with H3!'.split(' ')) {
controller.enqueue(encoder.encode(token))
await new Promise((resolve) => {
setTimeout(resolve, 300)
})
}
},
})
return stream
})
对于更高级的场景,您可以选择使用 sendStream(event, stream)
和 sendWebResponse(event, stream)
工具函数,而不是直接返回流。
对象语法事件处理程序
H3 引入了使用对象语法定义事件处理程序的支持。通过这种方法,您可以定义在每个处理程序运行之前或之后运行的钩子,例如身份验证或压缩中间件。
const auth = defineRequestMiddleware((event) => {
event.context.auth = { name: 'admin' }
})
const compression = defineResponseMiddleware((event) => {
// Example: https://stackblitz.com/edit/github-mb6bz3
})
export default eventHandler({
onRequest: [auth],
onBeforeResponse: [compression],
async handler(event) {
return `Hello ${event.context.auth?.name || 'Guest'}`
},
})
类型化事件处理程序请求
H3 现在支持使用新的泛型类型支持来定义事件类型。
当您定义类型时,请求工具将感知事件输入类型。此增强功能还使我们能够提高上游框架(如 Nitro 和 Nuxt)中 $fetch
处理程序的类型安全性。
export default eventHandler<{ body: { name: string }, query: { id: string } }>(
async (event) => {
const query = getQuery(event) // Query is typed as { id: string }
const body = await readBody(event) // Body is typed as { name: string }
},
)
运行时 + 类型安全的请求工具
两个新的工具函数 getValidatedQuery(event, validator)
和 readValidatedBody(event, validator)
方便与 zod 等模式验证器集成,以实现运行时和类型安全。
import { z } from 'zod'
const userSchema = z.object({
name: z.string().default('Guest'),
email: z.string().email(),
})
export default defineEventHandler(async (event) => {
const result = await readValidatedBody(event, body => userSchema.safeParse(body)) // or `.parse` to directly throw an error
if (!result.success)
throw result.error.issues
// User object is validated and typed!
return result.data
})
额外工具
我们还引入了其他几个工具,以进一步增强 Web 应用程序开发体验
getRequestIP(event, { xForwardedFor? })
:获取传入请求的 IP。readFormData(event)
:将请求体读取为 FormData。clearResponseHeaders(event)
:清除所有响应头。removeResponseHeader(event, name)
:移除特定的响应头。serveStatic(event, options)
:平台无关的静态资产服务器。请查看 listhen 源码,了解在 Node.js 中使用的示例。
借助 HMR 实现轻松的 TypeScript 开发
我们还发布了 unjs/listhen 的更新版本,它可以与 H3 应用程序无缝集成。
您只需创建一个 index.ts
文件
import { createApp, eventHandler } from 'h3'
export const app = createApp()
app.use('/', () => 'Hello world!')
运行 npx listhen@latest -w ./index.ts
以启动一个支持 TypeScript、热模块替换 (HMR) 和静态资产服务器的开发服务器。
完整变更日志
有关完整的变更列表,请参阅 发行说明。