feat: add store module HMR (#4582)

* feat: add store module HMR

* fix: replace export with window.$nuxt

Thanks to @pi0 for the suggestion :)

* refactor: apply only in dev mode on client side

* test: make store module test more descriptive

* fix: clear modules to apply HMR

* fix: remove console.log

* fix: e2e tests

* refactor: use void
This commit is contained in:
Alexander Lichter 2018-12-19 15:22:00 +00:00 committed by Sébastien Chopin
parent 5b58272d1a
commit b2eee1772e
4 changed files with 82 additions and 62 deletions

View File

@ -3,12 +3,14 @@ import Vuex from 'vuex'
Vue.use(Vuex)
const files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
const filenames = files.keys()
// Store
let storeData = {}
let files;
void function updateModules() {
files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
const filenames = files.keys()
// Check if {dir.store}/index.js exists
const indexFilename = filenames.find(filename => filename.includes('./index.'))
@ -19,7 +21,7 @@ if (indexFilename) {
// If store is not an exported method = modules store
if (typeof storeData !== 'function') {
// Store modules
if (!storeData.modules) {
if (!storeData.modules || module.hot) {
storeData.modules = {}
}
@ -69,7 +71,19 @@ if (typeof storeData !== 'function') {
module[name] = Object.assign({}, module[name], fileModule, appendedMods)
module[name].namespaced = true
}
// If the environment supports hot reloading...
<% if (isDev) { %>
if (process.client && module.hot) {
// Whenever any Vuex module is updated...
module.hot.accept(files.id, () => {
// Update `root.modules` with the latest definitions.
updateModules()
// Trigger a hot update in the store.
window.<%= globals.nuxt %>.$store.hotUpdate({ modules: storeData.modules })
})
}<% } %>
}
}()
// createStore
export const createStore = storeData instanceof Function ? storeData : () => {

View File

@ -78,8 +78,10 @@ describe('basic browser', () => {
test('/store', async () => {
await page.nuxt.navigate('/store')
expect(await page.$text('h1')).toBe('Vuex Nested Modules')
expect(await page.$text('p')).toBe('1')
expect(await page.$text('h1')).toBe('foo/bar/baz: Vuex Nested Modules')
expect(await page.$text('h2')).toBe('index/counter: 1')
expect(await page.$text('h3')).toBe('foo/blarg/getVal: 4')
expect(await page.$text('h4')).toBe('foo/bab/getBabVal: 10')
})
test('/head', async () => {

View File

@ -1,12 +1,14 @@
<template>
<div>
<h1>{{ baz }}</h1>
<h1>foo/bar/baz: {{ baz }}</h1>
<br>
<p>{{ $store.state.counter }}</p>
<h2>index/counter: {{ $store.state.counter }}</h2>
<br>
<h2>{{ getVal }}</h2>
<h3>foo/blarg/getVal: {{ getVal }}</h3>
<br>
<h3>{{ getBabVal }}</h3>
<h4>foo/bab/getBabVal: {{ getBabVal }}</h4>
<br>
<button @click="$store.commit('increment')">+1</button>
</div>
</template>

View File

@ -70,8 +70,10 @@ describe('basic ssr', () => {
test('/store', async () => {
const { html } = await nuxt.server.renderRoute('/store')
expect(html).toContain('<h1>Vuex Nested Modules</h1>')
expect(html).toContain('<p>1</p>')
expect(html).toContain('<h1>foo/bar/baz: Vuex Nested Modules</h1>')
expect(html).toContain('<h2>index/counter: 1</h2>')
expect(html).toContain('<h3>foo/blarg/getVal: 4</h3>')
expect(html).toContain('<h4>foo/bab/getBabVal: 10</h4>')
})
test('/head', async () => {