Skip to content

6. Exemplo [nuxt-03]: nuxtServerInit

O projeto [nuxt-03] tem como objetivo apresentar uma função do armazenamento [Vuex] denominada [nuxtServerInit]. Esta função permite ao servidor inicializar o armazenamento [Vuex], tal como faz a função [fetch]. No entanto, ao contrário da função [fetch], a função [nuxtServerInit] nunca é executada pelo cliente.

Image

O projeto [nuxt-03] é inicialmente obtido por cópia do projeto [nuxt-01], do qual se remove a página [page2] da pasta [pages] e do componente [navigation]. A pasta [store] é obtida por cópia da pasta [nuxt-02/store].

6.1. O store [Vuex]

A loja [Vuex] será implementada pelo seguinte ficheiro [store/index.js]:


/* eslint-disable no-console */
export const state = () => ({
  // contador
  counter: 0
})

export const mutations = {
  // incremento do contador em um valor [inc]
  increment(state, inc) {
    state.counter += inc
  }
}

export const actions = {
  async nuxtServerInit(store, context) {
    // quem executa este código?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
    // estamos à espera que uma promessa termine
    await new Promise(function(resolve, reject) {
      // normalmente, aqui temos uma função assíncrona
      // simulamo-la com uma espera de um segundo
      setTimeout(() => {
        // sucesso
        resolve()
      }, 1000)
    })
    // altera-se o store
    store.commit('increment', 34)
    // registo
    console.log('nuxtServerInit commit terminé')
  }
}
  • linhas 1-12: são análogas às que existiam no projeto [nuxt-02];
  • linhas 14-32: exporta-se um objeto [actions]. Trata-se de um termo reservado do armazenamento de [Vuex];
  • linha 15: define-se a função [nuxtServerInit]. Esta será executada pelo servidor no arranque da aplicação. A sua função habitual é inicializar um armazenamento [Vuex] utilizando dados externos obtidos através de uma função assíncrona. O [nuxt] aguarda que esta função retorne os seus resultados antes de iniciar o ciclo de vida da página solicitada. A função recebe dois parâmetros:
    • o store [Vuex] a ser inicializado;
    • o contexto [nuxt] do momento;
  • linhas 19-26: aguarda-se o fim da ação assíncrona, neste caso uma espera artificial de um segundo (linha 15);
  • linha 28: atribui-se ao contador o valor 34;
  • linhas 17 e 30: registos para acompanhar o desenrolar da execução da função [nuxtServerInit];

6.2. A página [index]

A página [index] será a seguinte:


<!-- página [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navegação -->
    <Navigation slot="left" />
    <!-- mensagem-->
    <b-alert slot="right" show variant="warning"> Home - value= {{ value }} </b-alert>
  </Layout>
</template>

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

import Layout from '@/components/layout'
import Navigation from '@/components/navigation'
export default {
  name: 'Home',
  // componentes utilizados
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // ciclo de vida
  beforeCreate() {
    // cliente e servidor
    console.log('[home beforeCreate]')
  },
  created() {
    // cliente e servidor
    this.value = this.$store.state.counter
    console.log('[home created], value=', this.value)
  },
  beforeMount() {
    // apenas cliente
    console.log('[home beforeMount]')
  },
  mounted() {
    // apenas cliente
    console.log('[home mounted]')
  }
}
</script>
  • linha 37: o valor do contador inicializado pela função [nuxtServerInit] é atribuído à propriedade [value] da linha 27. Este valor é apresentado na linha 7;
  • a linha 37 será executada tanto pelo servidor como pelo cliente. Em ambos os casos, a propriedade [value] receberá o mesmo valor, o que garante que a página gerada pelo servidor seja idêntica à gerada pelo cliente;

6.3. A página [page1]

A página [page1] é obtida por cópia da página [index]. Em seguida, altera-se o seu texto para substituir [home] por [page1]:


<!-- página [page1]] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navegação -->
    <Navigation slot="left" />
    <!-- mensagem-->
    <b-alert slot="right" show variant="warning"> Page1 - value= {{ value }} </b-alert>
  </Layout>
</template>

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

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

export default {
  name: 'Page1',
  // componentes utilizados
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // ciclo de vida
  beforeCreate() {
    // cliente e servidor
    console.log('[page1 beforeCreate]')
  },
  created() {
    // cliente e servidor
    this.value = this.$store.state.counter
    console.log('[page1 created], value=', this.value)
  },
  beforeMount() {
    // apenas cliente
    console.log('[page1 beforeMount]')
  },
  mounted() {
    // apenas cliente
    console.log('[page1 mounted]')
  }
}
</script>

Esta página existe apenas para permitir a navegação entre duas páginas.

6.4. Exécution

O ficheiro [nuxt.config.js] é alterado da seguinte forma:


// diretório do código-fonte
  srcDir: 'nuxt-03',
  // router
  router: {
    // raiz dos URL da aplicação
    base: '/nuxt-03/'
  },
  // servidor
  server: {
    // porta de serviço, 3000 por predefinição
    port: 81,
    // endereços de rede em escuta, por predefinição localhost: 127.0.0.1
    // 0.0.0.0 = todos os endereços de rede do computador
    host: 'localhost'
}

A página apresentada durante a execução é, então, a seguinte:

Image

  • No ficheiro [5], verifica-se que a função [nuxtServerInit] foi executada pelo servidor antes do ciclo de vida da página [index]. A função [nuxt] aguardou que a função assíncrona concluísse o seu trabalho antes de avançar para o ciclo de vida;
  • em [4], verifica-se que o cliente não executou a função [nuxtServerInit];

Agora, vamos navegar duas vezes: index --> página1 --> index. Os registos são então os seguintes:

Image

  • no [1-2], verifica-se que a função [nuxtServerInit] não é executada pelo cliente;

Agora, digitemos manualmente o URL da página [page1] para forçar uma chamada ao servidor:

Image

em [3-4], encontramos o mesmo mecanismo que antecedeu o carregamento da página [index] no arranque. Recorde-se aqui o que já foi dito: quando se força a chamada de uma página ao servidor, tudo acontece como se a aplicação reiniciasse com uma página inicial que seria a página solicitada;