Nuxt 生命周期

了解 Nuxt 应用的生命周期可以帮助你更深入地了解框架的运行方式,尤其是在服务器端和客户端渲染方面。

本章的目标是从高层次概述框架的各个部分、它们的执行顺序以及它们如何协同工作。

¥The goal of this chapter is to provide a high-level overview of the different parts of the framework, their execution order, and how they work together.

服务器

¥Server

在服务器上,对应用的每个初始请求都会执行以下步骤:

¥On the server, the following steps are executed for every initial request to your application:

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

¥Step 1: Setup Nitro Server and Nitro Plugins (Once)

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

¥Nuxt is powered by Nitro, a modern server engine.

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

¥When Nitro starts, it initializes and executes the plugins under the /server/plugins directory. These plugins can:

  • 捕获并处理应用范围的错误。
  • 注册在 Nitro 关闭时执行的钩子。
  • 注册用于请求生命周期事件(例如修改响应)的钩子。
Nitro 插件仅在服务器启动时执行一次。在无服务器环境中,服务器会在每次传入请求时启动,Nitro 插件也是如此。然而,它们不会被等待。¥Nitro plugins are executed only once when the server starts. In a serverless environment, the server boots on each incoming request, and so do the Nitro plugins. However, they are not awaited.
Read more in Docs > Guide > Directory Structure > Server#server Plugins.

步骤 2:Nitro 服务器中间件

¥Step 2: Nitro Server Middleware

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

¥After initializing the Nitro server, middleware under server/middleware/ is executed for every request. Middleware can be used for tasks such as authentication, logging, or request transformation.

从中间件返回值将终止请求并将返回值作为响应发送。通常应避免此行为以确保正确处理请求!¥Returning a value from middleware will terminate the request and send the returned value as the response. This behavior should generally be avoided to ensure proper request handling!
Read more in Docs > Guide > Directory Structure > Server#server Middleware.

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

¥Step 3: Initialize Nuxt and Execute Nuxt App Plugins

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

¥The Vue and Nuxt instances are created first. Afterward, Nuxt executes its server plugins. This includes:

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

插件按特定顺序执行,并且可能相互依赖。更多详情,请参阅 插件文档

¥Plugins execute in a specific order and may have dependencies on one another. For more details, including execution order and parallelism, refer to the Plugins documentation.

完成此步骤后,Nuxt 会调用 app:created 钩子,该钩子可用于执行其他逻辑。¥After this step, Nuxt calls the app:created hook, which can be used to execute additional logic.
Read more in Docs > Guide > Directory Structure > Plugins.

步骤 4:路由验证

¥Step 4: Route Validation

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

¥After initializing plugins and before executing middleware, Nuxt calls the validate method if it is defined in the definePageMeta function. The validate method, which can be synchronous or asynchronous, is often used to validate dynamic route parameters.

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

更多信息,请访问 路由验证文档

¥For more information, see the Route Validation documentation.

Read more in Docs > Getting Started > Routing#route Validation.

步骤 5:执行 Nuxt 应用中间件

¥Step 5: Execute Nuxt App Middleware

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

¥Middleware allows you to run code before navigating to a particular route. It is often used for tasks such as authentication, redirection, or logging.

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

¥In Nuxt, there are three types of middleware:

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

Nuxt 会在首次进入应用以及每次路由导航之前自动执行全局中间件。命名中间件和匿名中间件仅在相应页面组件中定义的 page(route) 元属性的 middleware 属性中指定的路由上执行。

¥Nuxt automatically executes global middleware for first time enter to the application and every time before route navigation. Named and anonymous middleware are executed only on the routes specified in the middleware property of the page(route) meta defined in the corresponding page components.

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

¥For details about each type and examples, see the Middleware documentation.

服务器上的任何重定向都会导致向浏览器发送 Location: 标头;然后浏览器会向这个新位置发出新的请求。发生这种情况时,所有应用状态都将被重置,除非已将其持久化到 Cookie 中。

¥Any redirection on the server will result in a Location: header being sent to the browser; the browser then makes a fresh request to this new location. All application state will be reset when this happens, unless persisted in a cookie.

Read more in Docs > Guide > Directory Structure > Middleware.

步骤 6:设置页面和组件

¥Step 6: Setup Page and Components

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

¥Nuxt initializes the page and its components during this step and fetches any required data with useFetch and useAsyncData. Since there are no dynamic updates and no DOM operations occur on the server, Vue lifecycle hooks such as onBeforeMount, onMounted, and subsequent hooks are NOT executed during SSR.

你应该避免在 <script setup> 的根作用域中编写会产生副作用且需要清理的代码。例如,在 setInterval 中设置计时器就是此类副作用的一个例子。在纯客户端代码中,我们可能会设置一个计时器,然后在 onBeforeUnmountonUnmounted 中将其拆除。但是,由于卸载钩子在 SSR 期间永远不会被调用,因此计时器将永远存在。为了避免这种情况,请将会产生副作用的代码移到 onMounted 中。

步骤 7:渲染并生成 HTML 输出

¥Step 7: Render and Generate HTML Output

所有组件初始化并获取数据后,Nuxt 会将组件与 unhead 中的设置相结合,生成完整的 HTML 文档。此 HTML 以及相关数据将发送回客户端以完成 SSR 流程。

¥After all components are initialized and data is fetched, Nuxt combines the components with settings from unhead to generate a complete HTML document. This HTML, along with the associated data, is sent back to the client to complete the SSR process.

将 Vue 应用渲染为 HTML 后,Nuxt 会调用 app:rendered 钩子。¥After rendering the Vue application to HTML, Nuxt calls the app:rendered hook.
在完成并发送 HTML 之前,Nitro 会调用 render:html 钩子。此钩子允许你操作生成的 HTML,例如注入其他脚本或修改元标记。¥Before finalizing and sending the HTML, Nitro will call the render:html hook. This hook allows you to manipulate the generated HTML, such as injecting additional scripts or modifying meta tags.

客户端(浏览器)

¥Client (browser)

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

¥This part of the lifecycle is fully executed in the browser, no matter which Nuxt mode you've chosen.

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

¥Step 1: Initialize Nuxt and Execute Nuxt App Plugins

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

¥This step is similar to the server-side execution and includes both built-in and custom plugins.

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

¥Custom plugins in the plugins/ directory, such as those without a suffix (e.g., myPlugin.ts) and with the .client suffix (e.g., myClientPlugin.client.ts), are executed on the client side.

完成此步骤后,Nuxt 会调用 app:created 钩子,该钩子可用于执行其他逻辑。¥After this step, Nuxt calls the app:created hook, which can be used to execute additional logic.
Read more in Docs > Guide > Directory Structure > Plugins.

步骤 2:路由验证

¥Step 2: Route Validation

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

¥This step is the same as the server-side execution and includes the validate method if defined in the definePageMeta function.

步骤 3:执行 Nuxt 应用中间件

¥Step 3: Execute Nuxt App Middleware

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

¥Nuxt middleware runs on both the server and the client. If you want certain code to run in specific environments, consider splitting it by using import.meta.client for the client and import.meta.server for the server.

Read more in Docs > Guide > Directory Structure > Middleware#when Middleware Runs.

步骤 4:挂载 Vue 应用和 Hydration

¥Step 4: Mount Vue Application and Hydration

调用 app.mount('#__nuxt') 会将 Vue 应用挂载到 DOM。如果应用使用 SSR 或 SSG 模式,Vue 会执行 hydrated 步骤,使客户端应用具有交互性。在 hydration 过程中,Vue 会重新创建应用(不包括 服务器组件),将每个组件与其对应的 DOM 节点匹配,并附加 DOM 事件监听器。

¥Calling app.mount('#__nuxt') mounts the Vue application to the DOM. If the application uses SSR or SSG mode, Vue performs a hydration step to make the client-side application interactive. During hydration, Vue recreates the application (excluding Server Components), matches each component to its corresponding DOM nodes, and attaches DOM event listeners.

为了确保正确数据融合,保持服务器和客户端数据之间的一致性非常重要。对于 API 请求,建议使用 useAsyncDatauseFetch 或其他支持 SSR 的组合项。这些方法确保在服务器端获取的数据在水合过程中被重用,从而避免重复请求。任何新的请求都应该在 hydration 之后触发,以防止 hydration 错误。

¥To ensure proper hydration, it's important to maintain consistency between the data on the server and the client. For API requests, it is recommended to use useAsyncData, useFetch, or other SSR-friendly composables. These methods ensure that the data fetched on the server side is reused during hydration, avoiding repeated requests. Any new requests should only be triggered after hydration, preventing hydration errors.

在安装 Vue 应用之前,Nuxt 会调用 app:beforeMount 钩子。¥Before mounting the Vue application, Nuxt calls the app:beforeMount hook.
挂载 Vue 应用后,Nuxt 会调用 app:mounted 钩子。¥After mounting the Vue application, Nuxt calls the app:mounted hook.

步骤 5:Vue 生命周期

¥Step 5: Vue Lifecycle

与服务器不同,浏览器会执行完整的 Vue 生命周期 操作。

¥Unlike on the server, the browser executes the full Vue lifecycle.