# Nuxt HTTP 请求生命周期

当一个 HTTP 请求发送到 Nuxt 应用时，它会经过一系列步骤，下面是完整的请求生命周期：

## 服务器端处理

### 1. Nitro 服务器初始化（仅一次）

- Nitro 服务器启动并初始化 `/server/plugins` 目录下的插件
- 这些插件只在服务器启动时执行一次
- 在无服务器环境中，每个请求都会启动服务器，但插件不会被等待执行完成

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-1-setup-nitro-server-and-nitro-plugins-once)

### 2. Nitro 服务器中间件

- 对于每个请求，执行 `server/middleware/` 下的中间件
- 这些中间件可用于身份验证、日志记录或请求转换
- 如果中间件返回值，请求将终止并将返回值作为响应

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-2-nitro-server-middleware)

### 3. 请求路由分发

根据请求路径，Nitro 将请求分发到不同的处理程序：

- 如果请求路径匹配 `/api/*`，则路由到 API 处理程序（`server/api/` 目录）
- 如果请求路径匹配 `server/routes/` 中定义的路由，则路由到相应的处理程序
- 如果是页面请求，则继续 Nuxt 应用的初始化

[服务器目录结构](https://nuxt.com/docs/guide/directory-structure/server)

### 4. API 处理（如果是 API 请求）

- 如果请求匹配 `server/api/` 目录中的路由，相应的处理程序将被执行
- 处理程序可以直接返回 JSON 数据、Promise 或使用 `event.node.res.end()` 发送响应
- API 处理完成后，请求结束，不会继续到 Vue 应用

[服务器 API](https://nuxt.com/docs/guide/directory-structure/server)

### 5. Nuxt 应用初始化（如果是页面请求）

- 创建 Vue 和 Nuxt 实例
- 执行 Nuxt 服务器插件，包括内置插件和 `plugins/` 目录中的自定义插件
- 调用 `app:created` 钩子

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-3-initialize-nuxt-and-execute-nuxt-app-plugins)

### 6. 路由验证

- 如果在 `definePageMeta` 中定义了 `validate` 方法，则调用该方法验证动态路由参数
- 如果验证失败，可能会终止请求或重定向

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-4-route-validation)

### 7. 执行 Nuxt 应用中间件

- 执行全局路由中间件、命名路由中间件和匿名路由中间件
- 中间件可以执行重定向，这会导致浏览器收到 `Location:` 头并发起新请求

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-5-execute-nuxt-app-middleware)

### 8. 页面和组件设置

- 初始化页面和组件
- 使用 `useFetch` 和 `useAsyncData` 获取所需数据
- 服务器端不执行 Vue 生命周期钩子如 `onBeforeMount`、`onMounted` 等

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-6-setup-page-and-components)

### 9. 渲染和生成 HTML 输出

- 将组件与 `unhead` 设置结合生成完整的 HTML 文档
- 调用 `app:rendered` 钩子
- 调用 `render:html` 钩子，允许操作生成的 HTML
- 将 HTML 和相关数据发送回客户端

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-7-render-and-generate-html-output)

## 客户端处理

### 1. 执行 Nuxt 应用中间件

- 中间件在服务器端和客户端都会运行
- 可以使用 `import.meta.client` 和 `import.meta.server` 区分环境

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-3-execute-nuxt-app-middleware)

### 2. 挂载 Vue 应用和水合

- 调用 `app:beforeMount` 钩子
- 调用 `app.mount('#__nuxt')` 将 Vue 应用挂载到 DOM
- Vue 执行水合步骤，使客户端应用程序具有交互性
- 调用 `app:mounted` 钩子

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-4-mount-vue-application-and-hydration)

### 3. Vue 生命周期

- 浏览器执行完整的 Vue 生命周期
- 包括 `onBeforeMount`、`onMounted` 等钩子

[Nuxt 生命周期](https://nuxt.com/docs/guide/concepts/nuxt-lifecycle#step-5-vue-lifecycle)

## 重要说明

- 服务器端重定向会导致浏览器收到 `Location:` 头并发起新请求，所有应用状态将重置
- 中间件在服务器端渲染和客户端水合期间都会执行，可能导致代码执行两次
- 对于 API 请求，建议使用 `useAsyncData`、`useFetch` 等 SSR 友好的组合式函数，确保服务器端获取的数据在水合期间被重用

[通用渲染](https://nuxt.com/docs/guide/concepts/rendering#universal-rendering)