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