111 lines
4.5 KiB
Markdown
111 lines
4.5 KiB
Markdown
# 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) |