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

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

Цель этой главы — дать обзор этапов работы фреймворка, порядка их выполнения и того, как они согласуются друг с другом.

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

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

Плагины сервера once

Nuxt использует Nitro — современный серверный движок.

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

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

Middleware сервера

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

Если middleware возвращает значение, запрос завершается и это значение уходит как ответ. Так обычно делать не стоит — ломается нормальная обработка запроса.
Узнать больше Docs > 3 X > Directory Structure > Server#server Middleware.

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

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

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

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

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

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

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

  • при успехе верните true;
  • при ошибке — false или объект с полями status и/или statusText, чтобы прервать запрос.

Подробнее: валидация маршрута.

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

Middleware приложения

Middleware выполняет код до перехода на маршрут: часто аутентификация, редиректы, логирование.

В Nuxt три вида middleware:

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

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

Детали и примеры: middleware.

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

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

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

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

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

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

Вывод HTML

Когда данные получены и компоненты отрендерены, Nuxt объединяет результат с настройками unhead в полный HTML-документ. HTML и связанные данные отправляются клиенту — SSR завершён.

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

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

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

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

Как на сервере: встроенные и пользовательские плагины.

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

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

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

Как на сервере: при наличии validate в definePageMeta.

Middleware приложения

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

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

Монтирование Vue и гидратация

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

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

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

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

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