Skip to content

6. Ejemplo [nuxt-03]: nuxtServerInit

El proyecto [nuxt-03] tiene como objetivo presentar una función del almacén [Vuex] denominada [nuxtServerInit]. Esta función permite al servidor inicializar el almacén [Vuex], al igual que lo hace la función [fetch]. Sin embargo, a diferencia de la función [fetch], la función [nuxtServerInit] nunca es ejecutada por el cliente.

Image

El proyecto [nuxt-03] se obtiene inicialmente mediante una copia del proyecto [nuxt-01], del que se elimina la página [page2] de la carpeta [pages] y del componente [navigation]. La carpeta [store] se obtiene copiando la carpeta [nuxt-02/store].

6.1. El store [Vuex]

La tienda [Vuex] se implementará mediante el siguiente archivo [store/index.js]:


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

export const mutations = {
  // incremento del contador en un valor [inc]
  increment(state, inc) {
    state.counter += inc
  }
}

export const actions = {
  async nuxtServerInit(store, context) {
    // ¿Quién ejecuta este código?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
    // se espera a que finalice una promesa
    await new Promise(function(resolve, reject) {
      // Normalmente, aquí hay una función asíncrona
      // la simulamos con una espera de un segundo
      setTimeout(() => {
        // Éxito
        resolve()
      }, 1000)
    })
    // se modifica el store
    store.commit('increment', 34)
    // registro
    console.log('nuxtServerInit commit terminé')
  }
}
  • líneas 1-12: son análogas a las del proyecto [nuxt-02];
  • líneas 14-32: se exporta un objeto [actions]. Se trata de un término reservado del almacén de [Vuex];
  • línea 15: se define la función [nuxtServerInit]. El servidor la ejecutará al iniciar la aplicación. Su función habitual es inicializar un almacén [Vuex] utilizando datos externos obtenidos mediante una función asíncrona. [nuxt] espera a que esta función devuelva sus resultados antes de iniciar el ciclo de vida de la página solicitada. La función recibe dos parámetros:
    • el almacén [Vuex] que se va a inicializar;
    • el contexto [nuxt] del momento;
  • líneas 19-26: se espera a que finalice la acción asíncrona; en este caso, una espera artificial de un segundo (línea 15);
  • línea 28: se asigna al contador el valor 34;
  • líneas 17 y 30: registros para seguir el desarrollo de la ejecución de la función [nuxtServerInit];

6.2. La página [index]

La página [index] será la siguiente:


<!-- página [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navegación -->
    <Navigation slot="left" />
    <!-- mensaje-->
    <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 y servidor
    console.log('[home beforeCreate]')
  },
  created() {
    // cliente y servidor
    this.value = this.$store.state.counter
    console.log('[home created], value=', this.value)
  },
  beforeMount() {
    // solo cliente
    console.log('[home beforeMount]')
  },
  mounted() {
    // solo cliente
    console.log('[home mounted]')
  }
}
</script>
  • línea 37: el valor del contador inicializado por la función [nuxtServerInit] se asigna a la propiedad [value] de la línea 27. Este valor se muestra en la línea 7;
  • la línea 37 se ejecutará tanto en el servidor como en el cliente. En ambos casos, la propiedad [value] recibirá el mismo valor, lo que garantiza que la página generada por el servidor sea idéntica a la generada por el cliente;

6.3. La página [page1]

La página [page1] se obtiene copiando la página [index]. A continuación, se modifica su texto para sustituir [home] por [page1]:


<!-- página [page1]] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navegación -->
    <Navigation slot="left" />
    <!-- mensaje-->
    <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 y servidor
    console.log('[page1 beforeCreate]')
  },
  created() {
    // cliente y servidor
    this.value = this.$store.state.counter
    console.log('[page1 created], value=', this.value)
  },
  beforeMount() {
    // solo cliente
    console.log('[page1 beforeMount]')
  },
  mounted() {
    // solo cliente
    console.log('[page1 mounted]')
  }
}
</script>

Esta página solo sirve para permitir la navegación entre dos páginas.

6.4. Exécution

El archivo [nuxt.config.js] se modifica de la siguiente manera:


// directorio del código fuente
  srcDir: 'nuxt-03',
  // enrutador
  router: {
    // raíz de los URL de la aplicación
    base: '/nuxt-03/'
  },
  // servidor
  server: {
    // puerto de servicio, 3000 por defecto
    port: 81,
    // direcciones de red a las que escucha, por defecto localhost: 127.0.0.1
    // 0.0.0.0 = todas las direcciones de red del equipo
    host: 'localhost'
}

La página que se muestra al ejecutarse es la siguiente:

Image

  • En [5], se observa que el servidor ha ejecutado la función [nuxtServerInit] antes del ciclo de vida de la página [index]. [nuxt] esperó a que la función asíncrona terminara su trabajo antes de pasar al ciclo de vida;
  • en [4], se observa que el cliente no ha ejecutado la función [nuxtServerInit];

Ahora naveguemos dos veces: índice --> página1 --> índice. Los registros son entonces los siguientes:

Image

  • En [1-2], vemos que el cliente no ejecuta la función [nuxtServerInit];

Ahora escribamos manualmente el URL de la página [page1] para forzar una llamada al servidor:

Image

En [3-4], encontramos el mismo mecanismo que el que precedió a la carga de la página [index] al inicio. Recordemos aquí lo que ya se ha dicho: cuando se fuerza la llamada de una página al servidor, todo ocurre como si la aplicación se reiniciara con una página de inicio que sería la página solicitada;