middleware
Nuxt предоставляет настраиваемую систему route middleware для использования в приложении, идеально подходящую для размещения кода, который вы хотите запустить перед переходом к определенному маршруту.
Существует три вида middleware для маршрутов:
- Анонимная (или встроенная) middleware маршрута определяется непосредственно на странице.
- Именованная middleware маршрута, размещенная в
middleware/
и автоматически загружаемая посредством асинхронного импорта при использовании на странице. - Глобальная middleware маршрута, размещенная в
middleware/
с суффиксом.global
, которая запускается при каждом изменении маршрута.
Первые два вида middleware можно определить в definePageMeta
.
myMiddleware
становится my-middleware
.Использование
Middleware маршрутов — это навигационные гварды, которые получают текущий маршрут и следующий маршрут в качестве аргументов.
export default defineNuxtRouteMiddleware((to, from) => {
if (to.params.id === '1') {
return abortNavigation()
}
// В реальном приложении вы, вероятно, не будете перенаправлять каждый маршрут на `/`,
// однако важно проверить `to.path` перед перенаправлением, иначе вы
// можете получить бесконечный цикл редиректа
if (to.path !== '/') {
return navigateTo('/')
}
})
Nuxt предоставляет два глобально доступных помощника, которые могут быть возвращены непосредственно из middleware.
navigateTo
- Перенаправляет на указанный маршрут.abortNavigation
- Прерывает навигацию с необязательным сообщением об ошибке.
В отличие от навигационных гвардов из vue-router
, третий аргумент next()
не передается, а перенаправление или отмена маршрута обрабатывается путем возврата значения из middleware.
Возможные возвращаемые значения:
- ничего (простой
return
или отсутствие возврата вообще) - не блокирует навигацию и переходит к следующей функции middleware, если таковая имеется, или завершает навигацию по маршруту return navigateTo('/')
- перенаправляет по указанному пути и устанавливает код перенаправления на302
Found, если перенаправление происходит на стороне сервераreturn navigateTo('/', { redirectCode: 301 })
- перенаправляет по указанному пути и устанавливает код перенаправления на301
Moved Permanently, если перенаправление происходит на стороне сервераreturn abortNavigation()
- останавливает текущую навигациюreturn abortNavigation(error)
- отклоняет текущую навигацию с ошибкой
Порядок middleware
Middleware работают в следующем порядке:
- Глобальные middleware
- Порядок middleware, определяемый страницей (если несколько middleware объявлены массивом)
Например, предположим, что у вас есть следующие middleware и компонент:
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// Пользовательская middleware
},
'auth',
],
});
</script>
Можно ожидать, что middleware будут запущены в следующем порядке:
analytics.global.ts
setup.global.ts
- Пользовательская встроенная middleware
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 требуется окружение браузера, например, если у вас есть сгенерированный сайт, агрессивно кэширующий ответы или вы хотите прочитать значение из локального хранилища.
Однако, если вы хотите избежать такого поведения, вы можете сделать следующее:
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
})
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
.
Настройка middleware во время сборки
Вместо использования definePageMeta
на каждой странице, вы можете добавить именованную middleware маршрута в хуке pages:extend
.
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)
}
}
})