Nuxt 生命周期

理解 Nuxt 应用程序的生命周期可以帮助你更深入地了解框架的运作方式,特别是对于服务器端和客户端渲染。

本章的目标是提供一个关于框架不同部分、它们的执行顺序以及它们如何协同工作的高级概述。

服务器

在服务器端,对于你的应用程序的每个初始请求,会执行以下步骤:

步骤 1:设置 Nitro 服务器和 Nitro 插件(一次)

Nuxt 由Nitro一个现代服务器引擎提供支持。

当 Nitro 启动时,它会初始化并执行 /server/plugins 目录下的插件。这些插件可以:

  • 捕获和处理应用程序范围的错误。
  • 注册在 Nitro 关闭时执行的钩子。
  • 注册用于请求生命周期事件的钩子,例如修改响应。
Nitro 插件只在服务器启动时执行一次。在无服务器环境中,服务器会在每个传入请求时启动,Nitro 插件也会如此。但是,它们不会被等待。
欲了解更多信息,请参阅 文档 > 4 X > 指南 > 目录结构 > Server#server Plugins

步骤 2:Nitro 服务器中间件

初始化 Nitro 服务器后,server/middleware/ 下的中间件会在每个请求中执行。中间件可用于身份验证、日志记录或请求转换等任务。

从中间件返回一个值将终止请求并将返回的值作为响应发送。通常应避免这种行为,以确保正确的请求处理!
欲了解更多信息,请参阅 文档 > 4 X > 指南 > 目录结构 > Server#server Middleware

步骤 3:初始化 Nuxt 并执行 Nuxt App 插件

首先创建 Vue 和 Nuxt 实例。之后,Nuxt 执行其服务器插件。这包括:

  • 内置插件,例如 Vue Router 和 unhead
  • app/plugins/ 目录中的自定义插件,包括没有后缀的(例如 myPlugin.ts)和带有 .server 后缀的(例如 myServerPlugin.server.ts)。

插件以特定顺序执行,并且可能相互依赖。有关更多详细信息,包括执行顺序和并行性,请参阅插件文档

在此步骤之后,Nuxt 调用 app:created 钩子,可用于执行额外逻辑。
请在文档 > 4 X > 指南 > 目录结构 > 插件中阅读更多内容。

步骤 4:路由验证

在初始化插件和执行中间件之前,如果 definePageMeta 函数中定义了 validate 方法,Nuxt 会调用该方法。validate 方法可以是同步或异步的,通常用于验证动态路由参数。

  • 如果参数有效,validate 函数应返回 true
  • 如果验证失败,它应该返回 false 或包含 statusCode 和/或 statusMessage 的对象以终止请求。

有关更多信息,请参阅路由验证文档

欲了解更多信息,请参阅 文档 > 4 X > 入门 > 路由#route Validation

步骤 5:执行 Nuxt App 中间件

中间件允许你在导航到特定路由之前运行代码。它通常用于身份验证、重定向或日志记录等任务。

在 Nuxt 中,有三种类型的中间件:

  • 全局路由中间件
  • 命名路由中间件
  • 匿名(或内联)路由中间件

Nuxt 在初始页面加载时(在服务器和客户端上)执行所有全局中间件,然后在任何客户端导航之前再次执行。命名和匿名中间件仅在相应页面组件中定义的页面(路由)元数据的 middleware 属性中指定的路由上执行。

有关每种类型和示例的详细信息,请参阅中间件文档

服务器上的任何重定向都将导致向浏览器发送 Location: 头;然后浏览器会向此新位置发出新的请求。除非持久化到 cookie 中,否则所有应用程序状态都将在此时重置。

更多信息请阅读:文档 > 4 X > 指南 > 目录结构 > App > Middleware

步骤 6:渲染页面和组件

在此步骤中,Nuxt 渲染页面及其组件,并使用 useFetchuseAsyncData 获取任何所需数据。由于在服务器上没有动态更新和 DOM 操作,Vue 生命周期钩子如 onBeforeMountonMounted 以及后续钩子在 SSR 期间**不会**执行。

默认情况下,Vue 在 SSR 期间暂停依赖跟踪以获得更好的性能。

服务器端没有响应性,因为 Vue SSR 将应用程序自上而下地渲染为静态 HTML,因此无法返回并修改已渲染的内容。
你应该避免在 <script setup> 的根作用域中生成需要清理的副作用代码。这种副作用的一个例子是使用 setInterval 设置计时器。在仅限客户端的代码中,我们可能会设置一个计时器,然后在 onBeforeUnmountonUnmounted 中将其清除。然而,由于卸载钩子在 SSR 期间永远不会被调用,计时器将永远存在。为了避免这种情况,请将副作用代码移到 onMounted 中。
观看 Daniel Roe 解释服务器渲染和全局状态的视频。

步骤 7:生成 HTML 输出

获取所有所需数据并渲染组件后,Nuxt 将渲染的组件与 unhead 中的设置结合起来,生成一个完整的 HTML 文档。然后,此 HTML 以及相关数据会发送回客户端以完成 SSR 过程。

将 Vue 应用程序渲染为 HTML 后,Nuxt 调用 app:rendered 钩子。
在最终确定和发送 HTML 之前,Nitro 将调用 render:html 钩子。此钩子允许你操作生成的 HTML,例如注入额外的脚本或修改元标签。

客户端(浏览器)

生命周期的这一部分完全在浏览器中执行,无论你选择哪种 Nuxt 模式。

步骤 1:初始化 Nuxt 并执行 Nuxt App 插件

此步骤与服务器端执行类似,包括内置插件和自定义插件。

app/plugins/ 目录中的自定义插件,例如没有后缀的(例如 myPlugin.ts)和带有 .client 后缀的(例如 myClientPlugin.client.ts),在客户端执行。

在此步骤之后,Nuxt 调用 app:created 钩子,可用于执行额外逻辑。
请在文档 > 4 X > 指南 > 目录结构 > 插件中阅读更多内容。

步骤 2:路由验证

此步骤与服务器端执行相同,包括如果 definePageMeta 函数中定义了 validate 方法。

步骤 3:执行 Nuxt App 中间件

Nuxt 中间件在服务器和客户端上运行。如果你希望某些代码在特定环境中运行,请考虑使用 import.meta.client 用于客户端,import.meta.server 用于服务器来拆分代码。

欲了解更多信息,请参阅 文档 > 4 X > 指南 > 目录结构 > App > Middleware#when Middleware Runs

步骤 4:挂载 Vue 应用程序和水合

调用 app.mount('#__nuxt') 将 Vue 应用程序挂载到 DOM。如果应用程序使用 SSR 或 SSG 模式,Vue 会执行水合步骤以使客户端应用程序具有交互性。在水合期间,Vue 会重新创建应用程序(服务器组件除外),将每个组件与其相应的 DOM 节点匹配,并附加 DOM 事件监听器。

为了确保正确的水合,保持服务器和客户端之间数据的一致性至关重要。对于 API 请求,建议使用 useAsyncDatauseFetch 或其他 SSR 友好的组合式函数。这些方法确保在水合期间重用服务器端获取的数据,避免重复请求。任何新的请求都应仅在水合后触发,以防止水合错误。

在挂载 Vue 应用程序之前,Nuxt 调用 app:beforeMount 钩子。
在挂载 Vue 应用程序之后,Nuxt 调用 app:mounted 钩子。

步骤 5:Vue 生命周期

与服务器不同,浏览器执行完整的Vue 生命周期.