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

Il progetto [nuxt-03] viene inizialmente creato clonando il progetto [nuxt-01], dal quale vengono rimossi la pagina [page2] nella cartella [pages] e il componente [navigation]. La cartella [store] viene creata clonando la cartella [nuxt-02/store].
6.1. Lo store [Vuex]
Lo store [Vuex] verrà implementato dal seguente file [store/index.js]:
/* eslint-disable no-console */
export const state = () => ({
// meter
counter: 0
})
export const mutations = {
// increment counter by one [inc] value
increment(state, inc) {
state.counter += inc
}
}
export const actions = {
async nuxtServerInit(store, context) {
// who executes this code?
console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
// waiting for a promise to be fulfilled
await new Promise(function(resolve, reject) {
// this is normally an asynchronous function
// we simulate it with a one-second wait
setTimeout(() => {
// success
resolve()
}, 1000)
})
// modify the blind
store.commit('increment', 34)
// log
console.log('nuxtServerInit commit terminé')
}
}
- righe 1–12: sono simili a quelle del progetto [nuxt-02];
- righe 14–32: esportiamo un oggetto [actions]. Si tratta di un termine riservato nello store [Vuex];
- riga 15: definiamo la funzione [nuxtServerInit]. Questa verrà eseguita dal server all'avvio dell'applicazione. Il suo ruolo abituale è quello di inizializzare uno store [Vuex] utilizzando dati esterni ottenuti tramite una funzione asincrona. [nuxt] attende che questa funzione restituisca i suoi risultati prima di iniziare il ciclo di vita della pagina richiesta. La funzione accetta due parametri:
- lo store [Vuex] da inizializzare;
- il contesto [Nuxt] corrente;
- righe 19–26: attendiamo il completamento dell'azione asincrona, in questo caso un'attesa artificiale di un secondo (riga 15);
- riga 28: il contatore viene impostato su 34;
- righe 17 e 30: log per tracciare l'esecuzione della funzione [nuxtServerInit];
6.2. La pagina [index]
La pagina [index] sarà la seguente:
<!-- page [index] -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<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',
// components used
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// life cycle
beforeCreate() {
// client and server
console.log('[home beforeCreate]')
},
created() {
// client and server
this.value = this.$store.state.counter
console.log('[home created], value=', this.value)
},
beforeMount() {
// customer only
console.log('[home beforeMount]')
},
mounted() {
// customer only
console.log('[home mounted]')
}
}
</script>
- Riga 37: Il valore del contatore inizializzato dalla funzione [nuxtServerInit] viene assegnato alla proprietà [value] alla riga 27. Questo valore viene visualizzato alla riga 7;
- la riga 37 verrà eseguita sia dal server che dal client. In entrambi i casi, la proprietà [value] riceverà lo stesso valore, garantendo che la pagina generata dal server corrisponda a quella generata dal client;
6.3. La pagina [page1]
La pagina [page1] si ottiene copiando la pagina [index]. Modifichiamo quindi il suo testo per sostituire [home] con [page1]:
<!-- page [page1]] -->
<template>
<Layout :left="true" :right="true">
<!-- navigation -->
<Navigation slot="left" />
<!-- message-->
<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',
// components used
components: {
Layout,
Navigation
},
data() {
return {
value: 0
}
},
// life cycle
beforeCreate() {
// client and server
console.log('[page1 beforeCreate]')
},
created() {
// client and server
this.value = this.$store.state.counter
console.log('[page1 created], value=', this.value)
},
beforeMount() {
// customer only
console.log('[page1 beforeMount]')
},
mounted() {
// customer only
console.log('[page1 mounted]')
}
}
</script>
Questa pagina serve solo a consentire la navigazione tra due pagine.
6.4. Esecuzione
Il file [nuxt.config.js] viene modificato come segue:
// source code directory
srcDir: 'nuxt-03',
// router
router: {
// application URL root
base: '/nuxt-03/'
},
// server
server: {
// service port, default 3000
port: 81,
// network addresses listened to, default localhost: 127.0.0.1
// 0.0.0.0 = all the machine's network addresses
host: 'localhost'
}
La pagina visualizzata al momento dell'esecuzione è quindi la seguente:

- in [5], si osserva 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 procedere con il ciclo di vita;
- in [4], vediamo che il client non ha eseguito la funzione [nuxtServerInit];
Ora navighiamo due volte: index --> page1 --> index. I log sono quindi i seguenti:

- In [1-2], vediamo che la funzione [nuxtServerInit] non viene eseguita dal client;
Ora digitiamo manualmente l'URL della pagina [page1] per forzare una chiamata al server:

In [3-4], vediamo lo stesso meccanismo che ha preceduto il caricamento della pagina [index] all'avvio. Ricapitoliamo quanto detto in precedenza: quando forziamo una pagina a chiamare il server, è come se l'applicazione si riavviasse con una pagina iniziale che è la pagina richiesta;