React

Middleware di route in Nuxt 3: chi gira e quando

Il middleware di route in Nuxt 3 gira prima della pagina: globale, nominato o in linea, e decide con navigateTo o abortNavigation se la navigazione continua.

In sintesi

  • Il middleware globale con suffisso .global gira su ogni navigazione; quello nominato solo dove definePageMeta lo elenca.
  • Restituisci navigateTo o abortNavigation: un middleware che finisce senza return lascia passare la navigazione.
  • Il middleware gira sul server al primo render e nel browser dopo: window e localStorage non sono disponibili.

In Nuxt 3 il middleware di route è una funzione che gira prima che la pagina venga mostrata: legge la rotta, può fermarla o rimandare altrove, e non restituisce dati al componente.

Tre tipi, tre momenti

Il middleware globale vive in middleware/ con il suffisso .global e gira su ogni navigazione; quello nominato gira solo dove definePageMeta lo elenca; quello scritto dentro definePageMeta vale per una pagina sola.

npx nuxi add middleware auth
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const { user } = useAuth();
  if (!user.value && to.path !== "/login") {
    return navigateTo(`/login?next=${to.fullPath}`);
  }
});

Dentro la pagina la lista si dichiara in definePageMeta ed è ordinata: Nuxt esegue prima il globale, poi i nominati nell'ordine dato, e si ferma al primo che cambia la navigazione.


definePageMeta({
  middleware: ["auth", "subscription"],
});

Il contesto cambia fra server e client

Alla prima richiesta il middleware gira sul server, dentro il render: lì useCookie legge il cookie della richiesta. Nelle navigazioni successive gira nel browser, e un accesso diretto al database non è più disponibile.

// middleware/redirects.global.ts
export default defineNuxtRouteMiddleware((to) => {
  if (to.path === "/old-shop") {
    return navigateTo("/shop", { redirectCode: 301 });
  }
});

Il valore di ritorno conta

Un middleware che finisce senza return lascia passare la navigazione. return navigateTo(...) la sostituisce, return abortNavigation() la annulla: restituire la promessa è ciò che fa attendere Nuxt quando la funzione è asincrona.

TipoDove viveQuando gira
Globalemiddleware/nome.global.tsOgni navigazione, prima dei nominati
Nominatomiddleware/nome.tsSolo le pagine che lo elencano in definePageMeta
In lineadefinePageMeta({ middleware: [...] })Una pagina sola, senza file separato

Il limite da mettere in conto

Il middleware protegge le pagine, non le server route: una chiamata a /api/orders non passa da lì e va controllata dentro l’handler. E in una pagina con prerender attivo il middleware non gira affatto.

Errori che si vedono

  • Dimenticare return davanti a navigateTo in un middleware asincrono: la navigazione prosegue e il redirect arriva tardi.
  • Leggere window o localStorage nel middleware: sul server non esistono e il render fallisce.
  • Mettere una query al database in un middleware globale: gira su ogni navigazione, anche quando il dato non serve.
  • Contare sul middleware per proteggere le API: le server route hanno un altro ingresso e nessun filtro.

I componenti da mettere dietro il middleware sono già pronti: PrimeVue e shadcn-vue si installano come sorgente, e il blocco login copre la pagina verso cui il middleware rimanda. Le cartelle del progetto sono in struttura di un progetto Nuxt 3, l’ordine delle guardie lato client in guardie di navigazione in Vue Router, il confronto fra framework in Vue 3 vs React.

Domande frequenti

Il middleware gira anche sulle server route?

No. Route middleware vale per le pagine: una chiamata a /api/... arriva all’handler senza passare di lì. Il controllo va ripetuto dentro la server route, che è l’unico punto in cui la richiesta è visibile.

Perché il redirect non parte?

Quasi sempre manca il return: in un middleware asincrono il chiamante deve attendere la promessa. Scrivi return navigateTo(...) invece di chiamare la funzione e continuare.

Globale o nominato?

Globale solo per ciò che vale su ogni pagina, come la lingua o un redirect di dominio. Tutto il resto va nominato, perché un middleware globale paga il suo costo su ogni navigazione.

Dove leggo i cookie?

Con useCookie, che funziona sia sul server sia nel browser. document.cookie esiste solo nel browser e durante il render sul server vale undefined.

Posso fermare la navigazione senza redirect?

Sì, con return abortNavigation(). La rotta resta quella corrente e non viene mostrato alcun errore: serve nei casi in cui un’azione è già in corso, non per negare un permesso.