6. 示例 [nuxt-03]:nuxtServerInit
[nuxt-03] 项目旨在演示一个名为 [nuxtServerInit] 的 [Vuex] 存储函数。它允许服务器初始化 [Vuex] 存储,就像 [fetch] 函数那样。但与 [fetch] 函数不同的是,[nuxtServerInit] 函数绝不会由客户端执行。

[nuxt-03] 项目最初是通过克隆 [nuxt-01] 项目创建的,随后从该项目中移除了 [pages] 文件夹中的 [page2] 页面以及 [navigation] 组件。通过克隆 [nuxt-02/store] 文件夹创建了 [store] 文件夹。
6.1. [Vuex] 存储
[Vuex] 存储将通过以下 [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é')
}
}
- 第 1–12 行:与 [nuxt-02] 项目中的内容类似;
- 第 14–32 行:我们导出一个 [actions] 对象。这是 [Vuex] 存储中的一个保留术语;
- 第 15 行:我们定义了 [nuxtServerInit] 函数。该函数将在应用程序启动时由服务器执行。其通常的作用是通过异步函数获取外部数据来初始化 [Vuex] 存储。在开始请求页面的生命周期之前,[nuxt] 会等待该函数返回结果。该函数接受两个参数:
- 待初始化的 [Vuex] 存储;
- 当前的 [Nuxt] 上下文;
- 第 19–26 行:我们等待异步操作完成,此处设置了 1 秒的人为等待(第 15 行);
- 第 28 行:将计数器设置为 34;
- 第 17 行和第 30 行:记录日志以追踪 [nuxtServerInit] 函数的执行情况;
6.2. [index] 页面
[index] 页面将如下所示:
<!-- 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>
- 第 37 行:由 [nuxtServerInit] 函数初始化的计数器值被赋值给第 27 行的 [value] 属性。该值由第 7 行显示;
- 第 37 行将在服务器端和客户端同时执行。在两种情况下,[value] 属性都将获得相同的值,从而确保服务器生成的页面与客户端生成的页面一致;
6.3. [page1] 页面
[page1] 页面是通过复制 [index] 页面获得的。随后,我们修改其文本,将 [home] 替换为 [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>
本页面仅用于在两个页面之间进行导航。
6.4. 执行
[nuxt.config.js] 文件修改如下:
// 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'
}
执行后显示的页面如下:

- 在 [5] 中,我们可以看到 [nuxtServerInit] 函数是在 [index] 页面的生命周期开始之前由服务器执行的。[nuxt] 会等待该异步函数完成工作后,才继续执行生命周期;
- 在 [4] 中,我们可以看到客户端并未执行 [nuxtServerInit] 函数;
现在让我们进行两次导航:index --> page1 --> index。此时日志如下:

- 在 [1-2] 中,我们可以看到客户端并未执行 [nuxtServerInit] 函数;
现在让我们手动输入 [page1] 页面的 URL,以强制调用服务器:

在 [3-4] 中,我们可以看到与启动时加载 [index] 页面时相同的机制。让我们回顾一下之前提到的内容:当我们强制页面调用服务器时,这就像应用程序正在重启,且请求的页面就是其首页;