服务引擎 Nitro
Nitro 是 Nuxt 的服务端引擎,提供了跨平台的服务端运行时。它是让 Nuxt 成为"全栈框架"的核心——没有 Nitro,Nuxt 只是一个前端框架。
为什么需要了解 Nitro?
| 你想做的事 | Nitro 的角色 |
|---|---|
| 写 API 接口 | Nitro 提供 server/api/ 和 defineEventHandler |
| 部署到不同平台 | Nitro 的"一次构建,处处部署" |
| 用 Redis 缓存 | Nitro 的存储层(unstorage) |
| 服务端启动时初始化 | Nitro 插件 |
| 每个 API 请求前做检查 | Nitro 中间件 |
你不需要"学 Nitro"
——Nitro 是 Nuxt 的内部引擎,你通过 Nuxt 的约定(server/ 目录)使用它。但了解 Nitro 的能力,能帮你更好地利用 Nuxt 的全栈特性。
Nitro 架构
┌─────────────┐
│ Nuxt App │
└──────┬──────┘
│
┌──────▼──────┐
│ Nitro │ ← 服务端引擎
└──────┬──────┘
│
┌────────────┼────────────┐
│ │ │
┌─────▼────┐ ┌────▼────┐ ┌────▼────┐
│ h3 │ │ unjs │ │ Deploy │
│ (HTTP) │ │ (工具链) │ │ (多平台) │
└──────────┘ └─────────┘ └─────────┘核心组成
| 组件 | 说明 | 你需要了解吗? |
|---|---|---|
| h3 | 轻量级 HTTP 框架,处理请求/响应 | 是——写 API 时用到的都是 h3 的 API |
| unjs | JavaScript 工具链(ofetch、unstorage 等) | 了解即可 |
| Rollup | 服务端代码打包 | 不需要 |
| unstorage | 跨平台存储层 | 用缓存时了解 |
h3 是什么?
它是 Nitro 团队开发的 HTTP 框架,类似 Express,但更轻量、更快、原生支持 TypeScript。你在 server/ 目录下写的每个 API,底层都是 h3 在处理。
h3 框架
h3 是 Nitro 使用的 HTTP 框架,所有服务端代码都基于 h3 编写。
事件处理器
// 每个 API 路由都是一个事件处理器
export default defineEventHandler((event) => {
// event 是 H3Event 对象,包含请求的所有信息
return { message: 'Hello' }
})event 对象是什么?
它是 h3 对 HTTP 请求的封装,包含:
- 请求方法(GET、POST 等)
- 请求 URL
- 请求头
- 请求体
- Cookie
- 路由参数
- 上下文(context)
所有的 readBody、getQuery、getRouterParam 等函数,都是从这个 event 对象中提取信息。
H3 请求工具
// 读取请求体(POST/PUT 请求)
const body = await readBody(event)
// body: { name: 'Alice', email: 'alice@example.com' }
// 读取查询参数(?page=1&size=20)
const query = getQuery(event)
// query: { page: '1', size: '20' } ← 注意:值都是 string 类型!
// 读取路由参数(/api/users/123)
const id = getRouterParam(event, 'id')
// id: '123'
// 读取请求头
const auth = getRequestHeader(event, 'authorization')
// 读取 Cookie
const cookies = parseCookies(event)
const token = getCookie(event, 'auth-token')
// 获取请求 URL
const url = getRequestURL(event)
// 设置响应状态码
setResponseStatus(event, 201)
// 设置响应头
setResponseHeader(event, 'x-custom', 'value')
// 发送重定向
await sendRedirect(event, '/new-page', 302)INFO
️ getQuery 返回的值都是 string!
const query = getQuery(event)
// ?page=1&size=20
// query.page 是 '1'(string),不是 1(number)
// 如果需要数字,手动转换:
const page = Number(query.page)事件上下文
可以在中间件中设置 event.context,在后续处理器中访问:
// server/middleware/auth.ts
export default defineEventHandler((event) => {
// 从 Cookie 中获取 token,验证后把用户信息存入 context
const token = getCookie(event, 'auth-token')
if (token) {
event.context.user = verifyToken(token) // 自定义字段
}
})
// server/api/me.ts
export default defineEventHandler((event) => {
// 在 API 中直接使用中间件设置的数据
return event.context.user
})event.context 的作用
在不同中间件和 API 之间传递数据,避免重复计算。类似于 Express 的 req.xxx,但更规范。
INFO
️ 类型安全:如果你使用了 event.context 建议扩展类型
// server/types/index.ts
declare module 'h3' {
interface H3EventContext {
user?: { id: number; name: string }
}
}通用部署
Nitro 最大的特点是一次构建,处处部署。通过预设(preset)支持多种部署目标:
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
preset: 'node-server', // 部署预设
},
})常用预设
| 预设 | 说明 | 适合场景 |
|---|---|---|
node-server | Node.js 服务器 | 传统 VPS/云服务器 |
node-cluster | Node.js 集群模式 | 高性能 Node.js 部署 |
vercel | Vercel 平台 | 快速部署,零配置 |
netlify | Netlify 平台 | 类似 Vercel |
cloudflare-pages | Cloudflare Pages | 边缘渲染,全球加速 |
deno-deploy | Deno Deploy | Deno 运行时 |
bun | Bun 运行时 | Bun 运行时 |
static | 纯静态站点 | 不需要服务器的纯静态网站 |
为什么"一次构建"能"处处部署"?
Nitro 把你的服务端代码编译为标准格式,不同预设生成不同入口文件,但业务逻辑不变。你写的 defineEventHandler 代码在所有平台上都一样,只是底层运行时不同。
Nitro 存储层
Nitro 提供跨平台的存储层,基于 unstorage:
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
storage: {
redis: {
driver: 'redis',
host: '127.0.0.1',
port: 6379,
},
},
},
})// server/api/cache.ts
export default defineEventHandler(async () => {
// 读取
const value = await useStorage('redis').getItem('key')
// 写入
await useStorage('redis').setItem('key', 'value')
// 删除
await useStorage('redis').removeItem('key')
// 列出所有 key
const keys = await useStorage('redis').getKeys()
return { value, keys }
})什么时候用存储层?
- 缓存 API 响应
- 存储会话数据
- 速率限制(rate limiting)
- 临时数据存储
支持的存储驱动:Redis、Cloudflare KV、Vercel KV、MongoDB、GitHub、本地文件系统等。
开发模式下
不配置存储时,Nitro 使用内存存储。生产环境建议配置 Redis 等持久化存储。
Nitro 配置
export default defineNuxtConfig({
nitro: {
// 部署预设
preset: 'node-server',
// 存储
storage: { /* ... */ },
// 环境变量前缀
envPrefix: 'NUXT_',
// 预渲染路由
prerender: {
routes: ['/about', '/blog'],
},
// 压缩
compress: true,
// 自定义 rollup 配置
rollupConfig: { /* ... */ },
},
})Nitro 钩子
// server/plugins/nitro.ts
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('request', (event) => {
console.log('请求到达', event.path)
})
nitroApp.hooks.hook('close', () => {
console.log('服务器关闭')
})
})Nitro 钩子 vs Nuxt 钩子的区别
- Nitro 钩子:服务端运行时事件(请求、关闭等)
- Nuxt 钩子:构建/开发时事件(页面扩展、配置等)
- 如果你需要"每个请求都执行"的逻辑,用 Nitro 钩子
Nitro vs Express
| 特性 | Nitro/h3 | Express |
|---|---|---|
| 体积 | 超轻量 | 较重 |
| TypeScript | 原生支持 | 需要额外配置 |
| SSR 集成 | 与 Nuxt 深度集成 | 需要手动配置 |
| 跨平台部署 | ✅ 原生支持 | ❌ 仅 Node.js |
| 自动导入 | ✅ | ❌ |
| 生态 | Nuxt 生态 | npm 生态 |
可以在 Nuxt 中用 Express 吗?
技术上可以,但不推荐。Nitro/h3 更轻量、类型更好、与 Nuxt 集成更深、部署更灵活。如果你习惯了 Express,h3 的 API 风格非常相似,上手很快。
知识脉络
自动导入 → 你在这里:服务引擎 Nitro
│
├─→ 相关:API 路由(09-服务端开发)
│
├─→ 相关:服务中间件(09-服务端开发)
│
└─→ 相关:部署上线(18-部署上线)