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.
| Tipo | Dove vive | Quando gira |
|---|---|---|
| Globale | middleware/nome.global.ts | Ogni navigazione, prima dei nominati |
| Nominato | middleware/nome.ts | Solo le pagine che lo elencano in definePageMeta |
| In linea | definePageMeta({ 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
returndavanti anavigateToin un middleware asincrono: la navigazione prosegue e il redirect arriva tardi. - Leggere
windowolocalStoragenel 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.