Изучите Nuxt с коллекцией из 100+ советов!

middleware

Nuxt предоставляет middleware для запуска кода перед переходом по определенному маршруту.

Nuxt предоставляет настраиваемую систему route middleware для использования в приложении, идеально подходящую для размещения кода, который вы хотите запустить перед переходом к определенному маршруту.

Существует три вида middleware для маршрутов:

  1. Анонимная (или встроенная) middleware маршрута определяется непосредственно на странице.
  2. Именованная middleware маршрута, размещенная в middleware/ и автоматически загружаемая посредством асинхронного импорта при использовании на странице.
  3. Глобальная middleware маршрута, размещенная в middleware/ с суффиксом .global, которая запускается при каждом изменении маршрута.

Первые два вида middleware можно определить в definePageMeta.

Имена middleware нормализуются до kebab-case: myMiddleware становится my-middleware.
Middleware маршрута запускается в части Vue-приложения Nuxt. Несмотря на похожее название, они полностью отличаются от серверных middleware, которые запускаются в части сервера приложения Nitro.

Использование

Middleware маршрутов — это навигационные гварды, которые получают текущий маршрут и следующий маршрут в качестве аргументов.

middleware/my-middleware.ts
export default 
defineNuxtRouteMiddleware
((
to
,
from
) => {
if (
to
.
params
.
id
=== '1') {
return
abortNavigation
()
} // В реальном приложении вы, вероятно, не будете перенаправлять каждый маршрут на `/`, // однако важно проверить `to.path` перед перенаправлением, иначе вы // можете получить бесконечный цикл редиректа if (
to
.
path
!== '/') {
return
navigateTo
('/')
} })

Nuxt предоставляет два глобально доступных помощника, которые могут быть возвращены непосредственно из middleware.

  1. navigateTo - Перенаправляет на указанный маршрут.
  2. abortNavigation - Прерывает навигацию с необязательным сообщением об ошибке.

В отличие от навигационных гвардов из vue-router, третий аргумент next() не передается, а перенаправление или отмена маршрута обрабатывается путем возврата значения из middleware.

Возможные возвращаемые значения:

  • ничего (простой return или отсутствие возврата вообще) - не блокирует навигацию и переходит к следующей функции middleware, если таковая имеется, или завершает навигацию по маршруту
  • return navigateTo('/') - перенаправляет по указанному пути и устанавливает код перенаправления на 302 Found, если перенаправление происходит на стороне сервера
  • return navigateTo('/', { redirectCode: 301 }) - перенаправляет по указанному пути и устанавливает код перенаправления на 301 Moved Permanently, если перенаправление происходит на стороне сервера
  • return abortNavigation() - останавливает текущую навигацию
  • return abortNavigation(error) - отклоняет текущую навигацию с ошибкой
Узнать больше Docs > API > Utils > Navigate To.
Узнать больше Docs > API > Utils > Abort Navigation.
Мы рекомендуем использовать вспомогательные функции, указанные выше, для выполнения редиректов или остановки навигации. Другие возможные возвращаемые значения, описанные в документации vue-router, могут работать, но в будущем могут произойти критические изменения.

Порядок middleware

Middleware работают в следующем порядке:

  1. Глобальные middleware
  2. Порядок middleware, определяемый страницей (если несколько middleware объявлены массивом)

Например, предположим, что у вас есть следующие middleware и компонент:

middleware/ directory
middleware/
--| analytics.global.ts
--| setup.global.ts
--| auth.ts
pages/profile.vue
<script setup lang="ts">
definePageMeta({
  middleware: [
    function (to, from) {
      // Пользовательская middleware
    },
    'auth',
  ],
});
</script>

Можно ожидать, что middleware будут запущены в следующем порядке:

  1. analytics.global.ts
  2. setup.global.ts
  3. Пользовательская встроенная middleware
  4. auth.ts

Порядок глобальных middleware

По умолчанию глобальные middleware выполняются в алфавитном порядке на основе имени файла.

Однако могут быть случаи, когда вы хотите установить определенный порядок. Например, в последнем сценарии setup.global.ts может потребоваться запустить перед analytics.global.ts. В этом случае мы рекомендуем снабдить глобальные middleware префиксом с «алфавитной» нумерацией.

Структура директории
middleware/
--| 01.setup.global.ts
--| 02.analytics.global.ts
--| auth.ts
Если вы новичок в «алфавитной» нумерации, помните, что имена файлов сортируются как строки, а не как числовые значения. Например, 10.new.global.ts будет предшествовать 2.new.global.ts. Вот почему в примере номера из одной цифры имеют префикс 0.

Когда запускаются middleware

Если сайт рендерится или генерируется сервером, middleware для начальной страницы будет выполняться как при рендеринге страницы, так и снова на клиенте. Это может быть необходимо, если вашей middleware требуется окружение браузера, например, если у вас есть сгенерированный сайт, агрессивно кэширующий ответы или вы хотите прочитать значение из локального хранилища.

Однако, если вы хотите избежать такого поведения, вы можете сделать следующее:

middleware/example.ts
export default 
defineNuxtRouteMiddleware
(
to
=> {
// пропустить middleware на сервере if (import.meta.
server
) return
// полностью пропустить middleware на стороне клиента if (import.meta.
client
) return
// или пропустить middleware только при начальной загрузке клиента const
nuxtApp
=
useNuxtApp
()
if (import.meta.
client
&&
nuxtApp
.
isHydrating
&&
nuxtApp
.
payload
.
serverRendered
) return
})
Отрисовка страницы ошибки — это совершенно отдельная загрузка страницы, что означает, что любая зарегистрированная middleware будет запущена снова. Вы можете использовать useError в middleware, чтобы проверить, обрабатывается ли ошибка.

Динамическое добавление middleware

Глобальную или именованную middleware маршрута можно добавить вручную с помощью вспомогательной функции addRouteMiddleware(), например, из плагина.

export default 
defineNuxtPlugin
(() => {
addRouteMiddleware
('global-test', () => {
console
.
log
('эта глобальная middleware была добавлена в плагин и будет запускаться при каждом изменении маршрута')
}, {
global
: true })
addRouteMiddleware
('named-test', () => {
console
.
log
('эта именованная middleware была добавлена в плагин и переопределит любую существующую middleware с тем же именем')
}) })

Пример

Структура директории
-| middleware/
---| auth.ts

В файле страницы вы можете сослаться на эту middleware маршрута:

<script setup lang="ts">
definePageMeta({
  middleware: ["auth"]
  // или middleware: 'auth'
})
</script>

Теперь, прежде чем переход на эту страницу сможет быть завершен, будет запущена middleware маршрута auth.

Прочитайте и отредактируйте живой пример в Docs > Examples > Routing > Middleware.

Настройка middleware во время сборки

Вместо использования definePageMeta на каждой странице, вы можете добавить именованную middleware маршрута в хуке pages:extend.

nuxt.config.ts
import type { 
NuxtPage
} from 'nuxt/schema'
export default
defineNuxtConfig
({
hooks
: {
'pages:extend' (
pages
) {
function
setMiddleware
(
pages
:
NuxtPage
[]) {
for (const
page
of
pages
) {
if (/* некоторое условие */ true) {
page
.
meta
||= {}
// Обратите внимание, что это переопределит любые middleware, заданные в `definePageMeta` на странице.
page
.
meta
.middleware = ['named']
} if (
page
.
children
) {
setMiddleware
(
page
.
children
)
} } }
setMiddleware
(
pages
)
} } })