nuxt logo

Traducción de Documentación (No Oficial)

middleware

Nuxt proporciona middleware para ejecutar código antes de navegar a una ruta particular.

Nuxt proporciona un marco de trabajo de middleware de ruta personalizable que puedes usar en toda tu aplicación, ideal para extraer código que deseas ejecutar antes de navegar a una ruta particular.

Hay tres tipos de middleware de ruta:

  1. Middleware de ruta anónimo (o en línea) se define directamente dentro de la página.
  2. Middleware de ruta nombrado, colocado en el directorio middleware/ y cargado automáticamente mediante importación asíncrona cuando se usa en una página.
  3. Middleware de ruta global, colocado en el directorio middleware/ con un sufijo .global y se ejecuta en cada cambio de ruta.

Los dos primeros tipos de middleware de ruta se pueden definir en definePageMeta.

El nombre del middleware se normaliza a kebab-case: myMiddleware se convierte en my-middleware.

El middleware de ruta se ejecuta dentro de la parte Vue de tu aplicación Nuxt. A pesar del nombre similar, son completamente diferentes del middleware del servidor, que se ejecutan en la parte del servidor Nitro de tu aplicación.

Uso

El middleware de ruta son guardianes de navegación que reciben la ruta actual y la siguiente ruta como argumentos.

middleware/my-middleware.ts
export default defineNuxtRouteMiddleware((to, from) => {
  if (to.params.id === '1') {
    return abortNavigation()
  }
  // En una aplicación real probablemente no redirigirías cada ruta a `/`
  // sin embargo, es importante verificar `to.path` antes de redirigir o podrías
  // entrar en un bucle de redirección infinito
  if (to.path !== '/') {
    return navigateTo('/')
  }
})

Nuxt proporciona dos ayudantes disponibles globalmente que se pueden devolver directamente desde el middleware.

  1. navigateTo - Redirige a la ruta dada
  2. abortNavigation - Aborta la navegación, con un mensaje de error opcional.

A diferencia de los guardianes de navegación de vue-router, no se pasa un tercer argumento next(), y la redirección o cancelación de la ruta se maneja devolviendo un valor desde el middleware.

Los valores de retorno posibles son:

  • nada (un simple return o no retornar nada) - no bloquea la navegación y pasará a la siguiente función de middleware, si la hay, o completará la navegación de la ruta
  • return navigateTo('/') - redirige a la ruta dada y establecerá el código de redirección a 302 Found si la redirección ocurre en el lado del servidor
  • return navigateTo('/', { redirectCode: 301 }) - redirige a la ruta dada y establecerá el código de redirección a 301 Moved Permanently si la redirección ocurre en el lado del servidor
  • return abortNavigation() - detiene la navegación actual
  • return abortNavigation(error) - rechaza la navegación actual con un error
Ver también api > utils > navigate-to Ver también api > utils > abort-navigation

Recomendamos usar las funciones de ayuda mencionadas anteriormente para realizar redirecciones o detener la navegación. Otros valores de retorno posibles descritos en la documentación de vue-router pueden funcionar, pero podrían haber cambios incompatibles en el futuro.

Orden del Middleware

El middleware se ejecuta en el siguiente orden:

  1. Middleware Global
  2. Orden del middleware definido en la página (si hay múltiples middleware declarados con la sintaxis de arreglo)

Por ejemplo, suponiendo que tienes el siguiente middleware y componente:

middleware/ directory
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
pages/profile.vue
definePageMeta({
  middleware: [
    function (to, from) {
      // Middleware en línea personalizado
    },
    'auth',
  ],
});

Puedes esperar que el middleware se ejecute en el siguiente orden:

  1. analytics.global.ts
  2. setup.global.ts
  3. Middleware en línea personalizado
  4. auth.ts

Ordenando el Middleware Global

Por defecto, el middleware global se ejecuta alfabéticamente basado en el nombre del archivo.

Sin embargo, puede haber ocasiones en las que desees definir un orden específico. Por ejemplo, en el último escenario, setup.global.ts puede necesitar ejecutarse antes que analytics.global.ts. En ese caso, recomendamos prefijar el middleware global con numeración 'alfabética'.

Estructura del directorio
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts

En caso de que seas nuevo en la numeración 'alfabética', recuerda que los nombres de archivo se ordenan como cadenas, no como valores numéricos. Por ejemplo, 10.new.global.ts vendría antes que 2.new.global.ts. Por eso el ejemplo prefija los números de un solo dígito con 0.

Cuándo se Ejecuta el Middleware

Si tu sitio es renderizado por el servidor o generado, el middleware para la página inicial se ejecutará tanto cuando la página se renderiza como luego en el cliente. Esto podría ser necesario si tu middleware necesita un entorno de navegador, como si tienes un sitio generado, cacheas respuestas agresivamente, o deseas leer un valor del almacenamiento local.

Sin embargo, si deseas evitar este comportamiento, puedes hacerlo:

middleware/example.ts
export default defineNuxtRouteMiddleware(to => {
  // omitir middleware en el servidor
  if (import.meta.server) return
  // omitir middleware en el lado del cliente completamente
  if (import.meta.client) return
  // o solo omitir middleware en la carga inicial del cliente
  const nuxtApp = useNuxtApp()
  if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})

Esto es cierto incluso si lanzas un error en tu middleware en el servidor, y se renderiza una página de error. El middleware aún se ejecutará nuevamente en el navegador.

Renderizar una página de error es una carga de página completamente separada, lo que significa que cualquier middleware registrado se ejecutará nuevamente. Puedes usar useError en el middleware para verificar si se está manejando un error.

Agregar Middleware Dinámicamente

Es posible agregar middleware de ruta global o nombrado manualmente usando la función de ayuda addRouteMiddleware(), como desde dentro de un plugin.

export default defineNuxtPlugin(() => {
  addRouteMiddleware('global-test', () => {
    console.log('este middleware global fue agregado en un plugin y se ejecutará en cada cambio de ruta')
  }, { global: true })

  addRouteMiddleware('named-test', () => {
    console.log('este middleware nombrado fue agregado en un plugin y sobrescribiría cualquier middleware existente con el mismo nombre')
  })
})

Ejemplo

Estructura del Directorio
-| middleware/
---| auth.ts

En tu archivo de página, puedes referenciar este middleware de ruta:

definePageMeta({
  middleware: ["auth"]
  // o middleware: 'auth'
})

Ahora, antes de que la navegación a esa página pueda completarse, se ejecutará el middleware de ruta auth.

Editar y previsualizar el código de ejemploexamples > routing > middleware

Configurando Middleware en Tiempo de Construcción

En lugar de usar definePageMeta en cada página, puedes agregar middleware de ruta nombrado dentro del hook 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 (/* alguna condición */ true) {
            page.meta ||= {}
            // Ten en cuenta que esto sobrescribirá cualquier middleware establecido en `definePageMeta` en la página
            page.meta.middleware = ['named']
          }
          if (page.children) {
            setMiddleware(page.children)
          }
        }
      }
      setMiddleware(pages)
    }
  }
})