11. Exemplo [nuxt-08]: middlewares de roteamento
Neste exemplo, apresentamos o conceito de middlewares de roteamento, scripts executados a cada mudança de rota.
O exemplo [nuxt-08] é obtido inicialmente por meio da cópia do projeto [nuxt-01]:

Os middlewares de roteamento devem estar em uma pasta chamada [middleware] [2]. Pode haver um roteamento em dois níveis:
- um roteamento aplicado a cada navegação. Esse roteamento é, então, declarado no arquivo [nuxt.config.js];
- um roteamento aplicado a uma página específica, quando esta é o destino do roteamento. Esse roteamento é, então, declarado nessa página de destino;
11.1. Roteamento geral
O arquivo [middleware / routing.js] garantirá o roteamento geral. Ele é objeto da seguinte declaração no arquivo [nuxt.config.js]:
router: {
base: '/nuxt-08/',
middleware: ['routing']
},
Os middlewares de roteamento geral são uma propriedade do roteador (linha 1). Pode haver vários middlewares de roteamento. É por isso que, na linha 3, o valor da propriedade [middleware] é uma matriz. Percebe-se que não se utiliza um caminho para designar o middleware. Ele será procurado automaticamente na pasta [middleware] do projeto;
O middleware [routing], neste caso, apenas gera logs:
/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
// quem executa esse 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)')
// primeiro argumento
const context = args[0]
// chaves de contexto
dumpkeys(routing + ', context', context)
// o aplicativo
dumpkeys(routing + ', context.app', context.app)
// a rota
dumpkeys(routing + ', context.route', context.route)
console.log(routing + ', context.route=', context.route)
// o roteador
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. Veremos 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 chega à página [index]. Para isso, precisamos inserir 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() {
// somente cliente
console.log('[home beforeMount]')
},
mounted() {
// somente cliente
console.log('[home mounted]')
},
// roteamento
middleware: ['index-routing']
}
</script>
- linha 34: a propriedade [middleware] lista os scripts a serem executados sempre que a próxima página exibida for a página [index]. Novamente, esses 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 esse 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)
// o aplicativo
dumpkeys(indexRouting + ', context.app', context.app)
// a rota
dumpkeys(indexRouting + ', context.route', context.route)
console.log(indexRouting + ', context.route=', context.route)
// o roteador
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 de [index-routing] é idêntico ao de [routing] e produz os mesmos resultados. O que nos interessa é verificar quando esses dois middlewares são executados.
11.3. Execução do projeto
Executamos o projeto. Os logs são, então, os seguintes:
É o script [routing] que é executado primeiro pelo servidor:
Vemos aqui o que havíamos obtido com os plug-ins.
- linha 15: a propriedade [redirect] é frequentemente utilizada em middlewares: ela permite alterar o destino do roteamento em andamento;
Em seguida, como a página que será exibida é a [index], o servidor executa o script [index-routing] e exibe os seguintes logs:
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 controle. Os logs passam a ser os seguintes:
Vemos, portanto, que, ao iniciar o aplicativo, o cliente não executa nenhum middleware. Isso significa que isso ocorrerá sempre que o usuário forçar uma chamada ao servidor. Os middlewares só são executados pelo cliente durante a navegação dentro do próprio cliente. Vamos, por exemplo, acessar a página [page1] (estamos na página [index]) usando o link [Page 1]. Os logs ficam assim:
- linha 2: o middleware [routing] é executado pelo cliente;
- linha 4: observe a propriedade [from]: essa é a rota de onde viemos;
- linha 9: [context.route] é a rota para a qual estamos indo;
- linhas 15-18: exibição da página [page1];
Agora, voltemos à página [index] pelo link [Home]. Os registros são, então, os seguintes:
- linhas 1-15: o cliente executa o middleware [routing]. Isso é normal. Ele é executado a cada mudança de rota;
- linhas 16-29: o cliente executa o middleware [index-routing], pois:
- [index] é o destino da rota atual (ver linha 23);
- a página [index] definiu um middleware, chamado [index-routing];
Vemos, portanto, que os middlewares de roteamento geral são executados pelo cliente antes dos middlewares associados às páginas.