Skip to content

6. Esempio [nuxt-03]: nuxtServerInit

Il progetto [nuxt-03] mira a presentare una funzione dello store [Vuex] denominata [nuxtServerInit]. Essa consente al server di inizializzare lo store [Vuex], proprio come fa la funzione [fetch]. Tuttavia, a differenza della funzione [fetch], la funzione [nuxtServerInit] non viene mai eseguita dal client.

Image

Il progetto [nuxt-03] viene inizialmente ottenuto copiando il progetto [nuxt-01], dal quale viene rimossa la pagina [page2] dalla cartella [pages] e dal componente [navigation]. La cartella [store] si ottiene copiando la cartella [nuxt-02/store].

6.1. Lo store [Vuex]

Lo store [Vuex] sarà implementato dal seguente file [store/index.js]:


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

export const mutations = {
  // incremento del contatore di un valore [inc]
  increment(state, inc) {
    state.counter += inc
  }
}

export const actions = {
  async nuxtServerInit(store, context) {
    // chi esegue questo codice?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
    // si attende la conclusione di una promessa
    await new Promise(function(resolve, reject) {
      // normalmente qui c'è una funzione asincrona
      // la simuliamo con un'attesa di un secondo
      setTimeout(() => {
        // Operazione riuscita
        resolve()
      }, 1000)
    })
    // si modifica lo store
    store.commit('increment', 34)
    // log
    console.log('nuxtServerInit commit terminé')
  }
}
  • righe 1-12: sono analoghe a quelle presenti nel progetto [nuxt-02];
  • righe 14-32: si esporta un oggetto [actions]. Si tratta di un termine riservato dello store di [Vuex];
  • riga 15: si definisce la funzione [nuxtServerInit]. Questa verrà eseguita all’avvio dell’applicazione da parte del server. Il suo ruolo abituale è quello di inizializzare uno store [Vuex] utilizzando dati esterni ottenuti tramite una funzione asincrona. [nuxt] attende che quest’ultima restituisca i risultati prima di avviare il ciclo di vita della pagina richiesta. La funzione riceve due parametri:
    • lo store [Vuex] da inizializzare;
    • il contesto [nuxt] del momento;
  • righe 19-26: si attende la fine dell’azione asincrona, in questo caso un’attesa artificiale di un secondo (riga 15);
  • riga 28: si assegna al contatore il valore 34;
  • righe 17 e 30: log per monitorare lo svolgimento dell'esecuzione della funzione [nuxtServerInit];

6.2. La pagina [index]

La pagina [index] sarà la seguente:


<!-- pagina [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigazione -->
    <Navigation slot="left" />
    <!-- messaggio-->
    <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',
  // componenti utilizzati
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // ciclo di vita
  beforeCreate() {
    // client e server
    console.log('[home beforeCreate]')
  },
  created() {
    // client e server
    this.value = this.$store.state.counter
    console.log('[home created], value=', this.value)
  },
  beforeMount() {
    // solo client
    console.log('[home beforeMount]')
  },
  mounted() {
    // solo client
    console.log('[home mounted]')
  }
}
</script>
  • riga 37: il valore del contatore inizializzato dalla funzione [nuxtServerInit] viene assegnato alla proprietà [value] della riga 27. Questo valore viene visualizzato dalla riga 7;
  • la riga 37 verrà eseguita sia dal server che dal client. In entrambi i casi, la proprietà [value] riceverà lo stesso valore, il che garantisce l’identità della pagina generata dal server con quella generata dal client;

6.3. La pagina [page1]

La pagina [page1] si ottiene copiando la pagina [index]. Si modifica quindi il testo per sostituire [home] con [page1]:


<!-- pagina [[page1]] -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigazione -->
    <Navigation slot="left" />
    <!-- messaggio-->
    <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',
  // componenti utilizzati
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // ciclo di vita
  beforeCreate() {
    // client e server
    console.log('[page1 beforeCreate]')
  },
  created() {
    // client e server
    this.value = this.$store.state.counter
    console.log('[page1 created], value=', this.value)
  },
  beforeMount() {
    // solo client
    console.log('[page1 beforeMount]')
  },
  mounted() {
    // solo client
    console.log('[page1 mounted]')
  }
}
</script>

Questa pagina serve esclusivamente a consentire la navigazione tra due pagine.

6.4. Exécution

Il file [nuxt.config.js] viene modificato come segue:


// directory del codice sorgente
  srcDir: 'nuxt-03',
  // router
  router: {
    // radice dei file URL dell'applicazione
    base: '/nuxt-03/'
  },
  // server
  server: {
    // porta di servizio, 3000 per impostazione predefinita
    port: 81,
    // indirizzi di rete in ascolto, per impostazione predefinita localhost: 127.0.0.1
    // 0.0.0.0 = tutti gli indirizzi di rete del computer
    host: 'localhost'
}

La pagina visualizzata all'esecuzione è quindi la seguente:

Image

  • in [5], si vede che la funzione [nuxtServerInit] è stata eseguita dal server prima del ciclo di vita della pagina [index]. [nuxt] ha atteso che la funzione asincrona completasse il proprio lavoro prima di passare al ciclo di vita;
  • in [4], si vede che il client non ha eseguito la funzione [nuxtServerInit];

Ora navighiamo due volte: index --> pagina1 --> index. I log sono quindi i seguenti:

Image

  • in [1-2], si vede che la funzione [nuxtServerInit] non viene eseguita dal client;

Ora digitiamo manualmente URL dalla pagina [page1] per forzare una chiamata al server:

Image

in [3-4], ritroviamo lo stesso meccanismo che aveva preceduto il caricamento della pagina [index] all’avvio. Ricordiamo qui quanto già detto: quando si forza la richiesta di una pagina al server, è come se l’applicazione si riavviasse con una pagina iniziale che sarebbe proprio la pagina richiesta;