官方文档:
https://h3.dev/guide
示例代码:
https://gitee.com/itshizhan/nuxt-inaction-course/tree/master/h3js_study/quick_start
先从一个简单的H3 start example 看起:
初始化一个项目
javascript
mkdir quick_start
pnpm init
// 注意安装方式,目前官方文档已经是v2 版本,但是还没有发布正式的npm包
pnpm add npm:h3-nightly@2x
Create a new file server.mjs
javascript
import { H3, serve } from "h3";
const app = new H3();
// eventHandler 是一个 handler: EventHandler | H3 类型
// EventHandler 是一个函数类型,它会接收一个 H3Event 对象作为参数,用于处理客户端的请求并返回响应。
// H3 则代表另一个 h3 应用实例,这意味着可以将一个 h3 应用嵌套到另一个 h3 应用中。
app.get("/", (event) => {
// 如果不设置Content-Type,表情符号可能乱码
event.res.headers.set("Content-Type", "text/plain;charset=UTF-8");
return "⚡️ Hello, Tadaa!";
});
serve(app, { port: 3000 });
执行代码
javascript
node --watch ./server.mjs
new H3() 执行逻辑
javascript
const app = new H3();
当执行上述代码时,会创建一个 h3 app instance , app 是一个微型服务器,能够匹配路由、生成响应,并处理生命周期钩子(如错误处理)。
我们可以看下 H3 的类型定义文件:
javascript
declare class H3 {
#private;
/**
* Global h3 instance config.
*/
readonly config: H3Config;
/**
* An h3 compatible event handler useful to compose multiple h3 app instances.
*/
handler: EventHandler<EventHandlerRequest, unknown | Promise<unknown>>;
/**
* Create a new h3 app instance
*
* @param config - h3 config
*/
constructor(config?: H3Config);
/**
* Websocket hooks compatible with [🔌 crossws](https://crossws.h3.dev/).
*/
get websocket(): WebSocketOptions;
/**
* A [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)-like API allowing to fetch app routes.
*
* Input can be a URL, relative path or standard [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object.
*
* Returned value is a standard [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) or a promise resolving to a Response.
*/
fetch(_request: Request | URL | string, options?: RequestInit, context?: H3EventContext): Response | Promise<Response>;
/**
* Resolve a route handler by method and path.
*/
resolve(method: HTTPMethod, path: string): Promise<ResolvedEventHandler | undefined>;
all(route: string, handler: EventHandler | H3): this;
get(route: string, handler: EventHandler | H3): this;
post(route: string, handler: EventHandler | H3): this;
put(route: string, handler: EventHandler | H3): this;
delete(route: string, handler: EventHandler | H3): this;
patch(route: string, handler: EventHandler | H3): this;
head(route: string, handler: EventHandler | H3): this;
options(route: string, handler: EventHandler | H3): this;
connect(route: string, handler: EventHandler | H3): this;
trace(route: string, handler: EventHandler | H3): this;
on(method: HTTPMethod | Lowercase<HTTPMethod> | "", route: string, handler: EventHandler | H3): this;
/**
* Register a global middleware
*
* Global middleware will be called before all routes on each request.
*
* If the first argument is a string, it will be used as the route.
*/
use(arg1: string | EventHandler | H3 | H3Route, arg2?: EventHandler | H3 | Partial<H3Route>, arg3?: Partial<H3Route>): this;
}
这段代码是一个 TypeScript 类型声明(type declaration),用于描述一个名为 H3
的类的接口和行为。这个类看起来是用于构建 HTTP 服务的一个轻量级框架,类似于 Express 或 Fastify,但更现代化、模块化,并且兼容 fetch
API 和 WebSocket。
下面我会逐行详细解释每个部分的作用和含义:
🧱 类定义
ts
declare class H3 {
#private;
}
#private;
: 表示该类中使用了私有字段(ES2021 私有字段语法),可能用于封装内部状态或配置。
🔧 只读属性:config
ts
readonly config: H3Config;
config
是一个只读属性,类型为H3Config
,表示这个类实例的全局配置对象。- 只读意味着一旦初始化后就不能被外部修改。
🔄 请求处理器:handler
ts
handler: EventHandler<EventHandlerRequest, unknown | Promise<unknown>>;
handler
是一个事件处理函数,接受请求并返回一个值或 Promise。- 它符合 Node.js/HTTP 服务器常见的“事件处理”模式。
- 类型
EventHandler<Request, Response>
意味着这是一个异步处理函数,接收请求,返回响应。
🛠 构造函数
ts
constructor(config?: H3Config);
- 构造函数可以传入一个可选的
H3Config
配置对象来初始化H3
实例。
🌐 Websocket 支持
ts
get websocket(): WebSocketOptions;
- 提供了一个 getter 方法
websocket
,返回 WebSocket 的配置选项。 - 这个特性说明
H3
可以与 WebSocket 一起工作。
🚀 fetch 方法(类似浏览器 Fetch API)
ts
fetch(_request: Request | URL | string, options?: RequestInit, context?: H3EventContext): Response | Promise<Response>;
- 提供一个类似浏览器
fetch()
的方法,允许你模拟发送 HTTP 请求到当前应用的路由。 - 参数:
_request
: 可以是字符串路径、URL 对象或标准的Request
对象。options
: 标准的RequestInit
,如 headers、body 等。context
: 自定义上下文信息(可选)。
- 返回值:标准
Response
或其 Promise。
🗺 路由解析器
ts
resolve(method: HTTPMethod, path: string): Promise<ResolvedEventHandler | undefined>;
- 根据 HTTP 方法(GET、POST 等)和路径查找对应的路由处理器。
- 返回的是一个
Promise
,因为可能需要异步加载模块或中间件。 - 如果找不到对应路由,返回
undefined
。
📦 HTTP 方法注册路由(all, get, post...)
ts
all(route: string, handler: EventHandler | H3): this;
get(route: string, handler: EventHandler | H3): this;
post(route: string, handler: EventHandler | H3): this;
...
- 提供了常见的 HTTP 方法绑定函数。
- 每个方法都接受一个路径
route
和一个处理器handler
。 - 处理器可以是一个
EventHandler
函数或者另一个H3
实例(支持嵌套路由或组合多个 app)。 - 返回
this
,意味着支持链式调用。
🧩 泛用的 on 方法
ts
on(method: HTTPMethod | Lowercase<HTTPMethod> | "", route: string, handler: EventHandler | H3): this;
- 更通用的路由注册方式,允许传入任意 HTTP 方法名(大小写不敏感)。
- 例如:
.on("GET", "/hello", handler)
或.on("", "/any", handler)
(监听所有方法)。
⚙ 注册中间件:use
ts
use(arg1: string | EventHandler | H3 | H3Route, arg2?: EventHandler | H3 | Partial<H3Route>, arg3?: Partial<H3Route>): this;
use
用于注册全局中间件。- 中间件会在每次请求开始时被调用。
- 参数灵活,支持多种传参形式:
use("/path", handler)
use(handler)
use("/path", h3App)
use({ path: '/path', handler })
🧠 总结
成员 | 类型 | 用途 |
---|---|---|
config |
只读属性 | 存储应用配置 |
handler |
属性 | 整体事件处理函数 |
websocket |
getter | 获取 WebSocket 配置 |
fetch |
方法 | 模拟请求当前应用路由 |
resolve |
方法 | 异步查找路由处理器 |
all , get , post ... |
方法 | 绑定特定 HTTP 方法的路由 |
on |
方法 | 泛用的路由绑定 |
use |
方法 | 添加中间件或子路由 |
H3 App Instance
上文提到,当穿件 h3 app instance 时, app 只是一个微型服务器,能够匹配路由、生成响应,并处理生命周期钩子(如错误处理)。 但是 app 本身还不是完整的http服务器,自身不能直接监听 HTTP 端口,不过可以借助 serve 函数来启动服务器并监听端口。
例如,我们可以借助于node
内置的 createServer
创建一个 http 服务器,并监听端口,通过 h3 app instance 来处理路由请求等。如下:
javascript
import { H3 } from "h3";
import { createServer } from 'node:http';
const app = new H3();
// eventHandler 是一个 handler: EventHandler | H3 类型
// EventHandler 是一个函数类型,它会接收一个 H3Event 对象作为参数,用于处理客户端的请求并返回响应。
// H3 则代表另一个 h3 应用实例,这意味着可以将一个 h3 应用嵌套到另一个 h3 应用中。
app.get("/", (event) => {
event.res.headers.set("Content-Type", "text/plain;charset=UTF-8");
return "⚡️ Hello, Tadaa!";
});
// serve(app, { port: 3000 });
// 创建HTTP服务器并将所有请求传递给H3实例处理
const serverCustom = createServer(async (req, res) => {
const response = await app.fetch(req.url, { method: req.method }, /* 可选的上下文 */);
res.writeHead(response.status, response.headers);
res.end(await response.text());
});
// 让服务器监听3000端口
serverCustom.listen(3000, () => {
console.log('Server is listening on port 3000');
});
h3 serve
实际上,h3 框架内置了一个serve
, 用来处理 app instance 在不同运行时环境的行为。
源码如下:
javascript
/**
* Serve the h3 app, automatically handles current runtime behavior.
*/
export function serve(app: H3, options?: Omit<ServerOptions, "fetch">): Server {
return srvxServe({ fetch: app.fetch, ...options });
}
即,我们可以通过下面的方式,启动一个h3的 http 服务。
javascript
import { H3, serve } from "h3";
const app = new H3();
app.get("/", () => "⚡️ Tadaa!");
// serve 基于 srvx 库
serve(app, { port: 3000 });
srvx(https://srvx.h3.dev/)
提供了一个统一的标准 API,用于基于标准网络平台原语(fetch、Request 和 Response)创建 HTTP 服务器,并且能够与 Deno、Bun 和 Node.js 无缝协作。
其基本用法即:
javascript
import { serve } from "srvx";
// 即上文srvxServe 的实现
const server = serve({
fetch(request) {
return new Response("👋 Hello there!");
},
});