f in x
Vue Router 4 — Routing Avanzato con Lazy Loading e Navigation Guards per App Performanti
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Vue Router 4 — Routing Avanzato con Lazy Loading e Navigation Guards per App Performanti

[2026-06-30] Author: Ing. Calogero Bono
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

La tua app Vue carica tutto in blocco e l'utente aspetta secondi prima di vedere la prima schermata. Ogni kilobyte che arriva subito è un potenziale cliente perso. Noi lo vediamo nei progetti che ci arrivano per audit: rotte statiche, bundle da 2MB, utenti che abbandonano. Il problema non è Vue, è come gestisci il router. Vue Router 4 dà il controllo totale su ciò che viene caricato e quando, ma la maggior parte delle app non lo sfrutta. Qui non parliamo di teoria: ti mostriamo esattamente come implementare lazy loading e navigation guards per avere un'app veloce, sicura e che scala.

Perché il lazy loading dei componenti è essenziale per le Vue app?

Quando definisci una route con component: MyComponent, tutto il codice di quel componente finisce nel bundle iniziale. Se hai 50 rotte, carichi 50 componenti anche se l'utente ne vede una sola. Il risultato: tempi di caricamento alti, Core Web Vitals sotto la media, utenti che se ne vanno. Il lazy loading risolve spezzando il codice in chunk caricati su richiesta. Noi, di Meteora Web, abbiamo ridotto bundle di app con oltre 60 rotte del 55% semplicemente passando a import dinamici nelle route.

Come funziona tecnicamente

Vue Router 4 supporta nativamente la sintassi () => import('./views/Dashboard.vue'). Quando l'utente naviga verso quella route, il browser scarica il chunk corrispondente. Nessuna libreria extra, nessun plugin. Funziona con Vite (che usa import dinamici nativi) e con webpack (che genera chunk separati).

Sponsored Protocol

// Prima: bundle unico
const routes = [
  { path: '/dashboard', component: Dashboard }
];

// Dopo: lazy loading
const routes = [
  { 
    path: '/dashboard', 
    component: () => import('./views/Dashboard.vue')
  }
];

Attenzione: se usi webpack, aggiungi un commento magico per dare un nome leggibile al chunk:

component: () => import(/* webpackChunkName: 'dashboard' */ './views/Dashboard.vue')

Con Vite non serve, ma puoi usare i /* @vite-ignore */ se necessario.

Come implementare il lazy loading delle route in Vue Router 4?

Partiamo da un file router/index.js tipico. Noi consigliamo di strutturare le rotte in array separati per sezione (es. pubbliche, protette, admin) e applicare lazy loading a ogni componente.

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home.vue')
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue')
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    meta: { requiresAuth: true }
  },
  // altre rotte...
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

Ogni rotta ora è lazy. Nessun cambiamento nel resto dell'app. Se hai rotte nidificate, applica lazy loading anche ai componenti delle rotte figlie.

Sponsored Protocol

Errore comune: dimenticare che anche il componente di layout o di fallback (404) deve essere lazy. Noi abbiamo visto app in cui la home era lazy ma il 404 no, vanificando parte del vantaggio.

Cosa sono le navigation guards e come proteggono le rotte?

Le navigation guards sono funzioni che si eseguono prima, durante o dopo una navigazione. Ti permettono di controllare se l'utente può accedere a una rotta, reindirizzarlo o mostrare un caricamento. Esistono tre livelli: globali (su ogni navigazione), per route (definite nella configurazione della rotta), per componente (nel componente stesso con onBeforeRouteLeave).

Guard globale beforeEach – il più comune

Lo usiamo per verificare l'autenticazione. Supponiamo che il tuo store Pinia contenga user. Se la rotta ha meta.requiresAuth: true, controlliamo se l'utente è loggato; altrimenti redirect a /login.

import { useAuthStore } from '@/stores/auth';

router.beforeEach((to, from, next) => {
  const authStore = useAuthStore();
  
  if (to.meta.requiresAuth && !authStore.user) {
    next({ name: 'Login', query: { redirect: to.fullPath } });
  } else {
    next();
  }
});

Nota: useAuthStore() deve essere chiamato dopo l'inizializzazione del router? No, funziona perché Pinia si attiva all'interno del contesto Vue. Ma se usi un composable generico, assicurati che sia disponibile o usa una semplice variabile reattiva.

Sponsored Protocol

Guard per route – più specifico

Puoi definire una guard direttamente nell'oggetto route, utile per logiche specifiche di una rotta.

const routes = [
  {
    path: '/admin',
    component: () => import('@/views/Admin.vue'),
    meta: { requiresAuth: true, role: 'admin' },
    beforeEnter: (to, from, next) => {
      const authStore = useAuthStore();
      if (authStore.user?.role !== 'admin') {
        next({ name: 'Forbidden' });
      } else {
        next();
      }
    }
  }
];

Attenzione: la guard per route non si attiva per le rotte figlie! Se hai rotte nidificate, devi replicare la guard o usare quella globale.

Quali strategie usare per le navigation guards in un'app reale?

Un errore comune è scrivere guard troppo generiche o duplicare la logica. Noi adottiamo questa architettura:

  • Guard globale unica: gestisce autenticazione e redirect. Se l'utente non è loggato e la rotta è protetta, reindirizza a /login salvando il percorso originale.
  • Meta campi: usa meta per flag come requiresAuth, role, guest (accessibile solo a utenti non loggati).
  • Gestione asincrona: se il check di autenticazione richiede una chiamata API (es. refresh token), esegui qui e non nel componente.
  • Per componenti avanzati: usa onBeforeRouteLeave per confermare uscite (es. form non salvato).
// Esempio di guard globale con check asincrono
router.beforeEach(async (to, from, next) => {
  const authStore = useAuthStore();
  
  // Se l'utente non è inizializzato e serve l'autenticazione, chiama API
  if (to.meta.requiresAuth && authStore.user === null) {
    try {
      await authStore.fetchUser();
    } catch (error) {
      // Token scaduto, redirect
      next({ name: 'Login' });
      return;
    }
  }
  
  if (to.meta.requiresAuth && !authStore.user) {
    next({ name: 'Login' });
  } else if (to.meta.guest && authStore.user) {
    next({ name: 'Dashboard' });
  } else {
    next();
  }
});

Come combinare lazy loading e guards per ottimizzare il caricamento?

Il lazy loading carica il codice del componente solo quando serve. Le navigation guards girano prima che il componente venga caricato. Questo significa che se la guard blocca l'accesso, il chunk non viene nemmeno richiesto. Risultato: risparmio di banda e performance migliori. Noi forziamo sempre questa combinazione: ogni rotta protetta ha meta.requiresAuth e la guard globale decide il destino prima di avviare l'import.

Sponsored Protocol

Esempio pratico: supponi una rotta /fatturazione che carica un componente pesante con librerie grafiche. Se l'utente non è loggato, la guard reindirizza subito e il chunk non viene scaricato. Meno traffico, più velocità generale.

Sponsored Protocol

// Route protetta e lazy
{
  path: '/fatturazione',
  component: () => import('@/views/Fatturazione.vue'),
  meta: { requiresAuth: true }
}

// La guard globale intercetta e se non auth, non scarica il chunk.

Attenzione: non usare beforeEnter con lazy loading se la guard dipende dal componente stesso (es. dati asincroni del componente). Per quello usa onBeforeRouteEnter nel componente.

Cosa fare adesso

  1. Scansiona tutte le tue route: ogni component: statico va convertito in component: () => import(...).
  2. Aggiungi una guard globale per autenticazione e, se serve, per ruoli. Usa meta per i permessi.
  3. Testa i nomi dei chunk in produzione: apri la scheda Network del DevTools e verifica che ogni navigazione carichi solo il chunk necessario.
  4. Verifica che le guard funzionino con reindirizzamenti corretti (salva la rotta originale per ridirigere dopo login).
  5. Controlla la copertura: quelle rotte che non vuoi siano lazy (es. landing page critica) possono rimanere statiche, ma tutte le altre vanno lazy.

Se vuoi approfondire l'intero approccio a Vue 3 e Composition API, leggi la nostra guida principale: Vue.js 3 e Composition API — Sviluppo Web Reattivo e Scalabile.

Per la documentazione ufficiale: Vue Router Lazy Loading.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()