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('/')- перенаправляет по указанному пути и устанавливает код перенаправления на302Found, если перенаправление происходит на стороне сервераreturn navigateTo('/', { redirectCode: 301 })- перенаправляет по указанному пути и устанавливает код перенаправления на301Moved 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.tssetup.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)
}
}
})