Nuxt 生命周期
本章的目标是提供对框架不同部分的高级概述、它们的执行顺序以及它们如何协同工作的理解。
服务器
在服务器端,对于每个对应用的初始请求,会执行以下步骤:
步骤 1:设置 Nitro 服务器和 Nitro 插件(一次性)
Nuxt 由现代服务器引擎 Nitro 提供支持。
当 Nitro 启动时,它会初始化并执行位于 /server/plugins 目录下的插件。这些插件可以:
- 捕获并处理全应用范围的错误。
- 注册在 Nitro 关闭时执行的钩子。
- 为请求生命周期事件注册钩子,例如修改响应。
步骤 2:Nitro 服务器中间件
在初始化 Nitro 服务器之后,server/middleware/ 下的中间件会在每个请求上执行。中间件可用于诸如认证、日志记录或请求转换等任务。
步骤 3:初始化 Nuxt 并执行 Nuxt 应用插件
首先创建 Vue 和 Nuxt 实例。随后,Nuxt 会执行其服务器端插件。这包括:
- 内置插件,例如 Vue Router 和
unhead。 - 位于
app/plugins/目录的自定义插件,包括无后缀的(例如myPlugin.ts)以及带.server后缀的(例如myServerPlugin.server.ts)。
插件按特定顺序执行,且可能相互依赖。有关执行顺序和并行性的更多详细信息,请参阅插件文档。
app:created 钩子,可用于执行额外逻辑。步骤 4:路由验证
在初始化插件并在执行页面中间件之前,如果在 definePageMeta 中定义了 validate 方法,Nuxt 会调用该方法。validate 方法可以是同步或异步的,通常用于验证动态路由参数。
- 如果参数有效,
validate函数应返回true。 - 如果验证失败,应返回
false或包含statusCode和/或statusMessage的对象以终止请求。
更多信息请参见路由验证文档。
步骤 5:执行 Nuxt 应用中间件
中间件允许你在导航到特定路由之前运行代码。它通常用于诸如认证、重定向或日志记录等任务。
在 Nuxt 中,有三种类型的中间件:
- 全局路由中间件
- 命名路由中间件
- 匿名(或内联)路由中间件
Nuxt 会在初始页面加载时(服务器和客户端均会)执行所有全局中间件,然后在任何客户端导航之前再次执行它们。命名和匿名中间件仅在相应页面组件的路由元信息中的 middleware 属性指定的路由上执行。
有关每种类型的详细信息和示例,请参阅中间件文档。
在服务器上的任何重定向都会导致发送一个 Location: 头到浏览器;浏览器随后对该新位置发起新的请求。发生这种情况时,除非将状态持久化到 cookie,否则所有应用状态都会被重置。
步骤 6:渲染页面和组件
Nuxt 在此步骤中渲染页面及其组件,并使用 useFetch 和 useAsyncData 获取任何所需的数据。由于服务器上不存在动态更新且不会发生 DOM 操作,Vue 生命周期钩子例如 onBeforeMount、onMounted 及随后的钩子在 SSR 期间是不会被执行的。
默认情况下,为了更好的性能,Vue 在 SSR 期间会暂停依赖追踪。
<script setup> 的根作用域中放置需要清理的副作用代码。一个示例是使用 setInterval 设置定时器。在仅客户端的代码中,我们可以在 onBeforeUnmount 或 onUnmounted 中销毁定时器。然而,因为在 SSR 期间卸载钩子永远不会被调用,这些定时器将永久存在。为避免此类问题,请将副作用代码移动到 onMounted 中。步骤 7:生成 HTML 输出
在获取所有所需数据并渲染组件之后,Nuxt 会将渲染的组件与 unhead 的设置结合,生成完整的 HTML 文档。此 HTML 及其相关数据随后会被发送回客户端,以完成 SSR 过程。
app:rendered 钩子。render:html 钩子。该钩子允许你操纵生成的 HTML,例如注入额外脚本或修改 meta 标签。客户端(浏览器)
这一部分的生命周期是在浏览器中完全执行的,无论你选择了哪种 Nuxt 模式。
步骤 1:初始化 Nuxt 并执行 Nuxt 应用插件
此步骤与服务器端的执行类似,包含内置插件和自定义插件。
app/plugins/ 目录中的自定义插件,例如无后缀的(例如 myPlugin.ts)以及带 .client 后缀的(例如 myClientPlugin.client.ts),会在客户端执行。
app:created 钩子,可用于执行额外逻辑。步骤 2:路由验证
此步骤与服务器端的执行相同,包含在 definePageMeta 中定义的 validate 方法。
步骤 3:执行 Nuxt 应用中间件
Nuxt 中间件在服务器和客户端都会运行。如果你希望某些代码在特定环境中运行,可以使用 import.meta.client(仅限客户端)和 import.meta.server(仅限服务器)将代码分隔开来。
步骤 4:挂载 Vue 应用并进行水合(Hydration)
调用 app.mount('#__nuxt') 会将 Vue 应用挂载到 DOM。如果应用使用了 SSR 或 SSG 模式,Vue 会执行水合步骤以使客户端应用具有交互性。在水合期间,Vue 会重建应用(不包括服务器组件),将每个组件与其对应的 DOM 节点匹配,并附加 DOM 事件监听器。
为确保正确的水合,需要保持服务器和客户端数据的一致性。对于 API 请求,建议使用 useAsyncData、useFetch 或其他对 SSR 友好的组合式函数。这些方法可确保在服务器端获取的数据在水合期间被重用,避免重复请求。任何新的请求都应在水合之后触发,以防止水合错误。
app:beforeMount 钩子。app:mounted 钩子。步骤 5:Vue 生命周期
与服务器不同,浏览器会完整执行 Vue 生命周期。