11. Exemplo [nuxt-08]: middlewares de encaminhamento
Neste exemplo, introduzimos o conceito de middlewares de encaminhamento, scripts executados sempre que ocorre uma mudança de rota.
O exemplo [nuxt-08] é obtido inicialmente através da cópia do projeto [nuxt-01]:

Os middlewares de encaminhamento devem estar numa pasta denominada [middleware] [2]. Pode existir um encaminhamento de dois níveis:
- um encaminhamento aplicado a cada navegação. Este é, então, objeto de uma declaração no ficheiro [nuxt.config.js];
- um encaminhamento aplicado a uma página específica, quando esta é o destino do encaminhamento. Este encaminhamento é, então, declarado nessa página de destino;
11.1. Roteamento geral
O ficheiro [middleware / routing.js] assegurará o encaminhamento geral. É objeto da seguinte declaração no ficheiro [nuxt.config.js]:
router: {
base: '/nuxt-08/',
middleware: ['routing']
},
Os middlewares de encaminhamento geral são uma propriedade do router (linha 1). Podem existir vários middlewares de encaminhamento. É por isso que, na linha 3, o valor da propriedade [middleware] é um tabuláro. Verifica-se que não se utiliza nenhum caminho para designar o middleware. Este será procurado automaticamente na pasta [middleware] do projeto;
O middleware [routing] limita-se aqui a registar logs:
/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
// quem executa este código?
console.log('[routing], process.server=', process.server, 'process.client=', process.client)
const who = process.server ? 'server' : 'client'
const routing = '[routing ' + who + ']'
// número de argumentos
console.log(routing + ', il y a', args.length, 'argument(s)')
// 1.º argumento
const context = args[0]
// chaves de contexto
dumpkeys(routing + ', context', context)
// a aplicação
dumpkeys(routing + ', context.app', context.app)
// a rota
dumpkeys(routing + ', context.route', context.route)
console.log(routing + ', context.route=', context.route)
// o router
dumpkeys(routing + ', context.app.router', context.app.router)
// o 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) {
// lista de chaves de [object]
const ligne = 'Liste des clés [' + message + ']'
console.log(ligne)
// lista de chaves
if (object) {
console.log(Object.keys(object))
}
}
- linha 3: vamos descobrir que o middleware recebe um argumento: o contexto do executor (servidor ou cliente);
- linhas 4-25: exibimos as propriedades de diferentes objetos para saber o que é utilizável. Vamos descobrir que o contexto do middleware é praticamente idêntico ao contexto do plugin;
11.2. Roteamento para uma página específica
Queremos controlar a forma como se acede à página [index]. Para tal, temos de introduzir a propriedade [middleware] nesta página [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',
// componentes utilizados
components: {
Layout,
Navigation
},
// ciclo de vida
beforeCreate() {
// cliente e servidor
console.log('[home beforeCreate]')
},
created() {
// cliente e servidor
console.log('[home created]')
},
beforeMount() {
// apenas cliente
console.log('[home beforeMount]')
},
mounted() {
// apenas cliente
console.log('[home mounted]')
},
// roteamento
middleware: ['index-routing']
}
</script>
- linha 34: a propriedade [middleware] lista os scripts a executar sempre que a próxima página apresentada for a página [index]. Mais uma vez, estes scripts serão procurados na pasta [middleware] do projeto;
O middleware [index-routing] é o seguinte:
/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
// quem executa este código?
console.log('[index-routing], process.server=', process.server, 'process.client=', process.client)
const who = process.server ? 'server' : 'client'
const indexRouting = '[index-routing ' + who + ']'
// número de argumentos
console.log(indexRouting + ', il y a', args.length, 'argument(s)')
// primeiro argumento
const context = args[0]
// chaves do contexto
dumpkeys(indexRouting + ', context', context)
// a aplicação
dumpkeys(indexRouting + ', context.app', context.app)
// a rota
dumpkeys(indexRouting + ', context.route', context.route)
console.log(indexRouting + ', context.route=', context.route)
// o router
dumpkeys(indexRouting + ', context.app.router', context.app.router)
// o 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)
// de onde viemos?
if (context.from) {
console.log('from=', context.from)
}
}
function dumpkeys(message, object) {
// lista de chaves de [object]
const ligne = 'Liste des clés [' + message + ']'
console.log(ligne)
// lista de chaves
if (object) {
console.log(Object.keys(object))
}
}
O código do [index-routing] é idêntico ao do [routing] e produz os mesmos resultados. O que nos interessa é verificar quando é que estes dois middlewares são executados.
11.3. Execução do projeto
Executamos o projeto. Os registos são então os seguintes:
É o script [routing] que é executado em primeiro lugar pelo servidor:
Vemos aqui o que obtivemos com os plugins.
- linha 15: a propriedade [redirect] é frequentemente utilizada nos middlewares: permite alterar o destino do encaminhamento em curso;
Em seguida, como a página que vai ser apresentada é a página [index], o servidor executa o script [index-routing] e apresenta os seguintes registos:
Os resultados obtidos com o script [index-routing] são semelhantes aos obtidos com o script [routing].
Assim que a página [index] é recebida pelo navegador do cliente, os scripts do cliente assumem o controlo. Os registos passam a ser os seguintes:
Vemos, portanto, que, no arranque da aplicação, o cliente não executa nenhum middleware. Isto significa que tal acontecerá sempre que o utilizador forçar uma chamada ao servidor. Os middlewares só são executados pelo cliente durante a navegação no próprio cliente. Vamos, por exemplo, aceder à página [page1] (estamos na página [index]) através do link [Page 1]. Os registos são então os seguintes:
- linha 2: o middleware [routing] é executado pelo cliente;
- linha 4: repare na propriedade [from]: é a rota de onde viemos;
- linha 9: [context.route] é a rota para onde nos dirigimos;
- linhas 15-18: exibição da página [page1];
Agora, voltemos à página [index] através do link [Home]. Os registos são então os seguintes:
- linhas 1-15: o cliente executa o middleware [routing]. Isto é normal. É executado sempre que há uma mudança de rota;
- linhas 16-29: o cliente executa o middleware [index-routing], porque:
- o [index] é o destino da rota atual (ver linha 23);
- a página [index] definiu um middleware, nomeadamente o [index-routing];
Vemos, portanto, que os middlewares de encaminhamento geral são executados pelo cliente antes dos middlewares associados às páginas.