Skip to content

6. Приклад [nuxt-03]: nuxtServerInit

Проєкт [nuxt-03] має на меті продемонструвати функцію сховища [Vuex] під назвою [nuxtServerInit]. Вона дозволяє серверу ініціалізувати сховище [Vuex] так само, як це робить функція [fetch]. Однак, на відміну від функції [fetch], функція [nuxtServerInit] ніколи не виконується клієнтом.

Image

Проєкт [nuxt-03] спочатку створюється шляхом копіювання проєкту [nuxt-01], з якого видаляється сторінка [page2] з папки [pages] та з компонента [navigation]. Папка [store] створюється шляхом копіювання папки [nuxt-02/store].

6.1. Штора [Vuex]

Файл [Vuex] буде реалізовано за допомогою наступного файлу [store/index.js]:


/* eslint-disable no-console */
export const state = () => ({
  // лічильник
  counter: 0
})

export const mutations = {
  // збільшення лічильника на одиницю [inc]
  increment(state, inc) {
    state.counter += inc
  }
}

export const actions = {
  async nuxtServerInit(store, context) {
    // хто виконує цей код?
    console.log('nuxtServerInit, client=', process.client, 'serveur=', process.server)
    // очікуємо завершення обіцянки
    await new Promise(function(resolve, reject) {
      // зазвичай тут використовується асинхронна функція
      // її імітують за допомогою очікування протягом однієї секунди
      setTimeout(() => {
        // успіх
        resolve()
      }, 1000)
    })
    // змінюємо значення в змінній
    store.commit('increment', 34)
    // журнал
    console.log('nuxtServerInit commit terminé')
  }
}
  • рядки 1–12: аналогічні тим, що були в проєкті [nuxt-02];
  • рядки 14–32: експортується об’єкт [actions]. Це зарезервований термін сховища [Vuex];
  • рядок 15: визначається функція [nuxtServerInit]. Вона буде виконана сервером під час запуску додатка. Зазвичай її завданням є ініціалізація сховища [Vuex] за допомогою зовнішніх даних, отриманих за допомогою асинхронної функції. [nuxt] очікує, поки ця функція поверне результати, перш ніж розпочати життєвий цикл запитуваної сторінки. Функція отримує два параметри:
    • сховище [Vuex], яке потрібно ініціалізувати;
    • поточний контекст [nuxt];
  • рядки 19–26: очікування завершення асинхронної дії, у даному випадку штучне очікування протягом однієї секунди (рядок 15);
  • рядок 28: лічильнику присвоюється значення 34;
  • рядки 17 і 30: записи в журналі для відстеження ходу виконання функції [nuxtServerInit];

6.2. Сторінка [index]

Сторінка [index] матиме такий вигляд:


<!-- сторінка [index] -->
<template>
  <Layout :left="true" :right="true">
    <!-- навігація -->
    <Navigation slot="left" />
    <!-- повідомлення-->
    <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: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // життєвий цикл
  beforeCreate() {
    // клієнт і сервер
    console.log('[home beforeCreate]')
  },
  created() {
    // клієнт і сервер
    this.value = this.$store.state.counter
    console.log('[home created], value=', this.value)
  },
  beforeMount() {
    // тільки клієнт
    console.log('[home beforeMount]')
  },
  mounted() {
    // тільки клієнт
    console.log('[home mounted]')
  }
}
</script>
  • рядок 37: значення лічильника, ініціалізованого функцією [nuxtServerInit], присвоюється властивості [value] з рядка 27. Це значення відображається у рядку 7;
  • рядок 37 буде виконано як сервером, так і клієнтом. В обох випадках властивість [value] отримає однакове значення, що забезпечує ідентичність сторінки, згенерованої сервером, та сторінки, згенерованої клієнтом;

6.3. Сторінка [page1]

Сторінка [page1] отримується шляхом копіювання сторінки [index]. Потім її текст змінюють, замінивши [home] на [page1]:


<!-- сторінка [page1]] -->
<template>
  <Layout :left="true" :right="true">
    <!-- навігація -->
    <Navigation slot="left" />
    <!-- повідомлення-->
    <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: {
    Layout,
    Navigation
  },
  data() {
    return {
      value: 0
    }
  },
  // життєвий цикл
  beforeCreate() {
    // клієнт і сервер
    console.log('[page1 beforeCreate]')
  },
  created() {
    // клієнт і сервер
    this.value = this.$store.state.counter
    console.log('[page1 created], value=', this.value)
  },
  beforeMount() {
    // тільки клієнт
    console.log('[page1 beforeMount]')
  },
  mounted() {
    // тільки клієнт
    console.log('[page1 mounted]')
  }
}
</script>

Ця сторінка призначена виключно для забезпечення навігації між двома сторінками.

6.4. Exécution

Файл [nuxt.config.js] змінюється наступним чином:


// каталог вихідного коду
  srcDir: 'nuxt-03',
  // маршрутизатор
  router: {
    // кореневий каталог URL додатка
    base: '/nuxt-03/'
  },
  // сервер
  server: {
    // порт служби, за замовчуванням 3000
    port: 81,
    // мережеві адреси, на яких відбувається прослуховування, за замовчуванням localhost: 127.0.0.1
    // 0.0.0.0 = усі мережеві адреси комп’ютера
    host: 'localhost'
}

Сторінка, що відображається під час виконання, має такий вигляд:

Image

  • У файлі [5] видно, що функція [nuxtServerInit] була виконана сервером до завершення життєвого циклу сторінки [index]. [nuxt] дочекалася завершення роботи асинхронної функції, перш ніж перейти до життєвого циклу;
  • у [4] видно, що клієнт не виконав функцію [nuxtServerInit];

Тепер перейдемо двічі: index --> page1 --> index. Журнали виглядають так:

Image

  • у [1-2] видно, що функція [nuxtServerInit] не виконується клієнтом;

Тепер введемо URL зі сторінки [page1] вручну, щоб примусово викликати сервер:

Image

у [3-4] ми бачимо той самий механізм, що й перед завантаженням сторінки [index] під час запуску. Нагадаємо те, про що вже йшлося: коли ми примусово викликаємо сторінку на сервері, все відбувається так, ніби додаток перезапускається зі стартовою сторінкою, якою є запитувана сторінка;