Skip to content

11. Esempio [nuxt-08]: middleware di routing

In questo esempio introduciamo il concetto di middleware di routing, ovvero script eseguiti ad ogni cambio di percorso.

L’esempio [nuxt-08] viene inizialmente ottenuto copiando il progetto [nuxt-01]:

Image

I middleware di routing devono trovarsi in una cartella denominata [middleware] [2]. È possibile avere un routing a due livelli:

  • un routing applicato a ogni navigazione. Questo viene quindi dichiarato nel file [nuxt.config.js];
  • un routing applicato a una pagina specifica, quando questa è la destinazione del routing. Tale routing viene quindi dichiarato in quella pagina di destinazione;

11.1. Routing generale

Il file [middleware / routing.js] garantirà l’instradamento generale. È oggetto della seguente dichiarazione nel file [nuxt.config.js]:


  router: {
    base: '/nuxt-08/',
    middleware: ['routing']
},

I middleware di instradamento generale sono una proprietà del router (riga 1). Possono esserci più middleware di instradamento. Per questo motivo, alla riga 3, il valore della proprietà [middleware] è un array. Si nota che non viene utilizzato alcun percorso per indicare il middleware. Verrà cercato automaticamente nella cartella [middleware] del progetto;

Il middleware [routing] in questo caso si limita a generare log:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // chi esegue questo codice?
  console.log('[routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const routing = '[routing ' + who + ']'
  // numero di argomenti
  console.log(routing + ', il y a', args.length, 'argument(s)')

  // primo argomento
  const context = args[0]
  // chiavi di contesto
  dumpkeys(routing + ', context', context)
  // l'applicazione
  dumpkeys(routing + ', context.app', context.app)
  // il percorso
  dumpkeys(routing + ', context.route', context.route)
  console.log(routing + ', context.route=', context.route)
  // il router
  dumpkeys(routing + ', context.app.router', context.app.router)
  // il router.options.routes
  dumpkeys(routing + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(routing + ', context.app.router.options.routes=', context.app.router.options.routes)
}

function dumpkeys(message, object) {
  // elenco delle chiavi di [object]
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // elenco delle chiavi
  if (object) {
    console.log(Object.keys(object))
  }
}
  • riga 3: scopriremo che il middleware riceve un argomento: il contesto dell’esecutore (server o client);
  • righe 4-25: vengono visualizzate le proprietà di diversi oggetti per capire cosa è utilizzabile. Si scoprirà che il contesto del middleware è quasi identico a quello del plugin;

11.2. Routing per una pagina specifica

Vogliamo controllare il modo in cui si accede alla pagina [index]. A tal fine, dobbiamo inserire la proprietà [middleware] in questa pagina [index]:


<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Home',
  // componenti utilizzati
  components: {
    Layout,
    Navigation
  },
  // ciclo di vita
  beforeCreate() {
    // client e server
    console.log('[home beforeCreate]')
  },
  created() {
    // client e server
    console.log('[home created]')
  },
  beforeMount() {
    // solo client
    console.log('[home beforeMount]')
  },
  mounted() {
    // solo client
    console.log('[home mounted]')
  },
  // instradamento
  middleware: ['index-routing']
}
</script>
  • riga 34: la proprietà [middleware] elenca gli script da eseguire ogni volta che la pagina successiva visualizzata è la pagina [index]. Anche in questo caso, tali script verranno cercati nella cartella [middleware] del progetto;

Il middleware [index-routing] è il seguente:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // chi esegue questo codice?
  console.log('[index-routing], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const indexRouting = '[index-routing ' + who + ']'
  // numero di argomenti
  console.log(indexRouting + ', il y a', args.length, 'argument(s)')

  // primo argomento
  const context = args[0]
  // chiavi del contesto
  dumpkeys(indexRouting + ', context', context)
  // l'applicazione
  dumpkeys(indexRouting + ', context.app', context.app)
  // la route
  dumpkeys(indexRouting + ', context.route', context.route)
  console.log(indexRouting + ', context.route=', context.route)
  // il router
  dumpkeys(indexRouting + ', context.app.router', context.app.router)
  // il router.options.routes
  dumpkeys(indexRouting + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(indexRouting + ', context.app.router.options.routes=', context.app.router.options.routes)
  // da dove veniamo?
  if (context.from) {
    console.log('from=', context.from)
  }
}

function dumpkeys(message, object) {
  // elenco delle chiavi di [object]
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // elenco delle chiavi
  if (object) {
    console.log(Object.keys(object))
  }
}

Il codice di [index-routing] è identico a quello di [routing] e produce gli stessi risultati. Ciò che ci interessa è vedere quando vengono eseguiti questi due middleware.

11.3. Esecuzione del progetto

Eseguiamo il progetto. I log sono quindi i seguenti:

È lo script [routing] che viene eseguito per primo dal server:

[routing], process.server= true process.client= false
[routing server], il y a 1 argument(s)
Liste des clés [[routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
   '$axios' ]
Liste des clés [[routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
   '$axios' ]
Liste des clés [[routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[routing server], context.route= { name: 'index',
  meta: [ {} ],
  path: '/',
  hash: '',
  query: {},
  params: {},
  fullPath: '/',
  matched:
   [ { path: '',
       regex: /^(?:\/(?=$))?$/i,
       components: [Object],
       instances: {},
       name: 'index',
       parent: undefined,
       matchAs: undefined,
       redirect: undefined,
       beforeEnter: undefined,
       meta: {},
       props: {} } ] }
Liste des clés [[routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

Qui ritroviamo ciò che avevamo ottenuto con i plugin.

  • riga 15: la proprietà [redirect] è spesso utilizzata nei middleware: consente di modificare la destinazione del routing in corso;

Quindi, poiché la pagina che verrà visualizzata è la pagina [index], il server esegue lo script [index-routing] e visualizza i seguenti log:

[index-routing], process.server= true process.client= false
[index-routing server], il y a 1 argument(s)
Liste des clés [[index-routing server], context]
[ 'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
   '$axios' ]
Liste des clés [[index-routing server], context.app]
[ 'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
   '$axios' ]
Liste des clés [[index-routing server], context.route]
[ 'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched' ]
[index-routing server], context.route= { name: 'index',
  meta: [ {} ],
  path: '/',
  hash: '',
  query: {},
  params: {},
  fullPath: '/',
  matched:
   [ { path: '',
       regex: /^(?:\/(?=$))?$/i,
       components: [Object],
       instances: {},
       name: 'index',
       parent: undefined,
       matchAs: undefined,
       redirect: undefined,
       beforeEnter: undefined,
       meta: {},
       props: {} } ] }
Liste des clés [[index-routing server], context.app.router]
[ 'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history' ]
Liste des clés [[index-routing server], context.app.router.options.routes]
[ '0', '1', '2' ]
[index-routing server], context.app.router.options.routes= [ { path: '/page1',
    component: [Function: _61cefe10],
    name: 'page1' },
  { path: '/page2',
    component: [Function: _61dd1591],
    name: 'page2' },
  { path: '/', component: [Function: _00d5e140], name: 'index' } ]

I risultati ottenuti con lo script [index-routing] sono analoghi a quelli ottenuti con lo script [routing].

Una volta che la pagina [index] è stata ricevuta dal browser client, subentrano gli script client. I log diventano i seguenti:

1
2
3
4
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]

Si nota quindi che all’avvio dell’applicazione il client non esegue alcun middleware. Ciò significa che ciò avverrà ogni volta che l’utente effettuerà una richiesta al server. I middleware vengono eseguiti dal client solo durante la navigazione all’interno dell’applicazione stessa. Navighiamo ad esempio verso la pagina [page1] (ci troviamo sulla pagina [index]) tramite il link [Page 1]. I log sono quindi i seguenti:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[page1 beforeCreate]
[page1 created]
[page1 beforeMount]
[page1 mounted]
  • riga 2: il middleware [routing] viene eseguito dal client;
  • riga 4: si noti la proprietà [from]: è la route da cui si proviene;
  • riga 9: [context.route] è la route di destinazione;
  • righe 15-18: visualizzazione della pagina [page1];

Ora torniamo alla pagina [index] tramite il link [Home]. I log sono quindi i seguenti:

[routing], process.server= false process.client= true
[routing client], il y a 1 argument(s)
Liste des clés [[routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
[index-routing], process.server= false process.client= true
[index-routing client], il y a 1 argument(s)
Liste des clés [[index-routing client], context]
(18) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios", "from"]
Liste des clés [[index-routing client], context.app]
(14) ["router", "nuxt", "head", "render", "data", "beforeCreate", "created", "mounted", "watch", "computed", "methods", "components", "context", "$axios"]
Liste des clés [[index-routing client], context.route]
(8) ["name", "meta", "path", "hash", "query", "params", "fullPath", "matched"]
[index-routing client], context.route= {name: "index", meta: Array(1), path: "/", hash: "", query: {}, }
Liste des clés [[index-routing client], context.app.router]
(10) ["app", "apps", "options", "beforeHooks", "resolveHooks", "afterHooks", "matcher", "fallback", "mode", "history"]
Liste des clés [[index-routing client], context.app.router.options.routes]
(3) ["0", "1", "2"]
[index-routing client], context.app.router.options.routes= (3) [{}, {}, {}]0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
from= {name: "page1", meta: Array(1), path: "/page1", hash: "", query: {}, }
[home beforeCreate]
[home created]
[home beforeMount]
[home mounted]
  • righe 1-15: il client esegue il middleware [routing]. È normale. Viene eseguito ad ogni cambio di percorso;
  • righe 16-29: il client esegue il middleware [index-routing], poiché:
    • [index] è la destinazione della route corrente (cfr. riga 23);
    • la pagina [index] ha definito un middleware, denominato [index-routing];

Si nota quindi che i middleware di routing generale vengono eseguiti dal client prima dei middleware associati alle pagine.