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