Жизненный цикл Nuxt

Понимание жизненного цикла приложений Nuxt помогает разобраться в работе фреймворка при серверном и клиентском рендеринге.

В этой главе даётся общий обзор частей фреймворка, порядка их выполнения и взаимодействия.

Жизненный цикл на сервере

На сервере при каждом первом запросе к приложению выполняются следующие шаги:

Серверные плагины once

Nuxt работает на Nitro — современном серверном движке.

При старте Nitro инициализирует и выполняет плагины из директории /server/plugins. Эти плагины могут:

  • перехватывать и обрабатывать глобальные ошибки;
  • регистрировать хуки при завершении работы Nitro;
  • регистрировать хуки жизненного цикла запроса, например для изменения ответов.
Плагины Nitro выполняются один раз при запуске сервера. В serverless-среде сервер поднимается при каждом запросе, и плагины Nitro тоже; при этом их выполнение не ожидается (не awaited).
Узнать больше Docs > 4 X > Directory Structure > Server#server Plugins.

Серверный middleware

После инициализации Nitro для каждого запроса выполняется middleware из server/middleware/. Его можно использовать для аутентификации, логирования, преобразования запросов и т.п.

Возврат значения из middleware завершает обработку запроса и отправляет это значение как ответ. Обычно так делать не стоит — это может нарушить корректную обработку запросов.
Узнать больше Docs > 4 X > Directory Structure > Server#server Middleware.

Плагины приложения

Сначала создаются экземпляры Vue и Nuxt, затем выполняются плагины приложения:

  • встроенные плагины (Vue Router, unhead и др.);
  • пользовательские плагины из app/plugins/, в том числе без суффикса (например myPlugin.ts) и с суффиксом .server (например myServerPlugin.server.ts).

Плагины выполняются в определённом порядке и могут зависеть друг от друга. Подробнее о порядке и параллельном выполнении — в документации по плагинам.

После этого шага Nuxt вызывает хук app:created, в котором можно выполнить дополнительную логику.
Узнать больше Docs > 4 X > Directory Structure > App > Plugins.

Валидация маршрута

После инициализации плагинов и до выполнения middleware Nuxt вызывает метод validate, если он задан в definePageMeta. Метод validate (синхронный или асинхронный) часто используется для проверки параметров динамического маршрута.

  • validate должен возвращать true, если параметры допустимы.
  • При ошибке валидации — вернуть false или объект с полями status и/или statusText, чтобы завершить запрос.

Подробнее — в документации по валидации маршрутов.

Узнать больше Docs > 4 X > Getting Started > Routing#route Validation.

Middleware приложения

Middleware позволяет выполнять код до перехода на маршрут — например, для проверки авторизации, редиректа или логирования.

В Nuxt есть три типа middleware:

  • глобальный маршрутный middleware;
  • именованный маршрутный middleware;
  • анонимный (инлайн) маршрутный middleware.

Nuxt выполняет весь глобальный middleware при первой загрузке страницы (и на сервере, и на клиенте), а затем перед каждой клиентской навигацией. Именованный и анонимный middleware выполняются только для маршрутов, указанных в meta страницы в свойстве middleware.

Подробнее и примеры — в документации по middleware.

Редирект на сервере приводит к отправке заголовка Location: в браузер; браузер делает новый запрос по этому адресу. Состояние приложения при этом сбрасывается, если оно не сохранено (например, в cookie).

Узнать больше Docs > 4 X > Directory Structure > App > Middleware.

Страница и компоненты

Nuxt рендерит страницу и её компоненты и при необходимости запрашивает данные через useFetch и useAsyncData. На сервере нет динамических обновлений и работы с DOM, поэтому хуки жизненного цикла Vue вроде onBeforeMount, onMounted и последующие не выполняются при SSR.

По умолчанию Vue приостанавливает отслеживание зависимостей во время SSR для производительности.

Реактивности на сервере нет: Vue при SSR рендерит приложение сверху вниз в статический HTML, поэтому уже отрендеренный контент изменить нельзя.
Избегайте побочных эффектов в корневой области <script setup>, требующих очистки. Например, таймеры через setInterval: на клиенте таймер можно остановить в onBeforeUnmount или onUnmounted, но при SSR эти хуки не вызываются, и таймеры останутся висеть. Выносите такой код в onMounted.
Видео от Daniel Roe: Server Rendering and Global State.

HTML на выходе

После загрузки данных и рендеринга компонентов Nuxt объединяет результат с настройками из unhead и формирует полный HTML-документ. Этот HTML вместе с данными отправляется клиенту и завершает этап SSR.

После рендеринга Vue-приложения в HTML Nuxt вызывает хук app:rendered.
Перед финальной отправкой HTML Nitro вызывает хук render:html. В нём можно изменить сгенерированный HTML — например, добавить скрипты или поправить meta-теги.

Жизненный цикл на клиенте

Эта часть жизненного цикла выполняется целиком в браузере, независимо от выбранного режима Nuxt.

Плагины приложения

Шаг аналогичен серверному: выполняются встроенные и пользовательские плагины.

Пользовательские плагины из app/plugins/ без суффикса (например myPlugin.ts) и с суффиксом .client (например myClientPlugin.client.ts) выполняются на клиенте.

После этого шага Nuxt вызывает хук app:created.
Узнать больше Docs > 4 X > Directory Structure > App > Plugins.

Валидация маршрута

То же, что на сервере: при наличии метода validate в definePageMeta он вызывается.

Middleware приложения

Middleware Nuxt выполняется и на сервере, и на клиенте. Чтобы код выполнялся только в одном окружении, разделяйте его с помощью import.meta.client и import.meta.server.

Узнать больше Docs > 4 X > Directory Structure > App > Middleware#when Middleware Runs.

Монтирование Vue-приложения и гидрация

Вызов app.mount('#__nuxt') монтирует Vue-приложение в DOM. При использовании SSR или SSG Vue выполняет гидрацию, чтобы сделать приложение интерактивным. При гидрации Vue заново создаёт приложение (кроме Server Components), сопоставляет компоненты с узлами DOM и подключает обработчики событий.

Чтобы гидрация прошла корректно, данные на сервере и клиенте должны совпадать. Для запросов к API рекомендуется использовать useAsyncData, useFetch или другие SSR-совместимые композаблы — они переиспользуют данные с сервера при гидрации и избегают повторных запросов. Новые запросы должны выполняться только после гидрации, иначе возможны ошибки гидрации.

Перед монтированием Vue-приложения Nuxt вызывает хук app:beforeMount.
После монтирования Nuxt вызывает хук app:mounted.

Жизненный цикл Vue

В браузере выполняется полный жизненный цикл Vue, в отличие от сервера.