starwait/docs/06-Nuxt生命周期.md
2025-04-25 11:33:24 +08:00

111 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)