mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
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:
parent
5b58272d1a
commit
b2eee1772e
@ -3,73 +3,87 @@ import Vuex from 'vuex'
|
|||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
const files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
|
|
||||||
const filenames = files.keys()
|
|
||||||
|
|
||||||
// Store
|
|
||||||
let storeData = {}
|
let storeData = {}
|
||||||
|
|
||||||
// Check if {dir.store}/index.js exists
|
let files;
|
||||||
const indexFilename = filenames.find(filename => filename.includes('./index.'))
|
|
||||||
|
|
||||||
if (indexFilename) {
|
void function updateModules() {
|
||||||
storeData = getModule(indexFilename)
|
files = require.context('@/<%= dir.store %>', true, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
|
||||||
}
|
const filenames = files.keys()
|
||||||
|
|
||||||
// If store is not an exported method = modules store
|
// Check if {dir.store}/index.js exists
|
||||||
if (typeof storeData !== 'function') {
|
const indexFilename = filenames.find(filename => filename.includes('./index.'))
|
||||||
// Store modules
|
|
||||||
if (!storeData.modules) {
|
if (indexFilename) {
|
||||||
storeData.modules = {}
|
storeData = getModule(indexFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const filename of filenames) {
|
// If store is not an exported method = modules store
|
||||||
let name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '')
|
if (typeof storeData !== 'function') {
|
||||||
if (name === 'index') continue
|
// Store modules
|
||||||
|
if (!storeData.modules || module.hot) {
|
||||||
const namePath = name.split(/\//)
|
storeData.modules = {}
|
||||||
|
|
||||||
name = namePath[namePath.length - 1]
|
|
||||||
if (['state', 'getters', 'actions', 'mutations'].includes(name)) {
|
|
||||||
const module = getModuleNamespace(storeData, namePath, true)
|
|
||||||
appendModule(module, filename, name)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If file is foo/index.js, it should be saved as foo
|
for (const filename of filenames) {
|
||||||
const isIndex = (name === 'index')
|
let name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '')
|
||||||
if (isIndex) {
|
if (name === 'index') continue
|
||||||
namePath.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
const module = getModuleNamespace(storeData, namePath)
|
const namePath = name.split(/\//)
|
||||||
const fileModule = getModule(filename)
|
|
||||||
|
|
||||||
name = namePath.pop()
|
name = namePath[namePath.length - 1]
|
||||||
module[name] = module[name] || {}
|
if (['state', 'getters', 'actions', 'mutations'].includes(name)) {
|
||||||
|
const module = getModuleNamespace(storeData, namePath, true)
|
||||||
// if file is foo.js, existing properties take priority
|
appendModule(module, filename, name)
|
||||||
// because it's the least specific case
|
continue
|
||||||
if (!isIndex) {
|
|
||||||
module[name] = Object.assign({}, fileModule, module[name])
|
|
||||||
module[name].namespaced = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// if file is foo/index.js we want to overwrite properties from foo.js
|
|
||||||
// but not from appended mods like foo/actions.js
|
|
||||||
const appendedMods = {}
|
|
||||||
if (module[name].appends) {
|
|
||||||
appendedMods.appends = module[name].appends
|
|
||||||
for (const append of module[name].appends) {
|
|
||||||
appendedMods[append] = module[name][append]
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
module[name] = Object.assign({}, module[name], fileModule, appendedMods)
|
// If file is foo/index.js, it should be saved as foo
|
||||||
module[name].namespaced = true
|
const isIndex = (name === 'index')
|
||||||
|
if (isIndex) {
|
||||||
|
namePath.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
const module = getModuleNamespace(storeData, namePath)
|
||||||
|
const fileModule = getModule(filename)
|
||||||
|
|
||||||
|
name = namePath.pop()
|
||||||
|
module[name] = module[name] || {}
|
||||||
|
|
||||||
|
// if file is foo.js, existing properties take priority
|
||||||
|
// because it's the least specific case
|
||||||
|
if (!isIndex) {
|
||||||
|
module[name] = Object.assign({}, fileModule, module[name])
|
||||||
|
module[name].namespaced = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if file is foo/index.js we want to overwrite properties from foo.js
|
||||||
|
// but not from appended mods like foo/actions.js
|
||||||
|
const appendedMods = {}
|
||||||
|
if (module[name].appends) {
|
||||||
|
appendedMods.appends = module[name].appends
|
||||||
|
for (const append of module[name].appends) {
|
||||||
|
appendedMods[append] = module[name][append]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// createStore
|
||||||
export const createStore = storeData instanceof Function ? storeData : () => {
|
export const createStore = storeData instanceof Function ? storeData : () => {
|
||||||
|
@ -78,8 +78,10 @@ describe('basic browser', () => {
|
|||||||
test('/store', async () => {
|
test('/store', async () => {
|
||||||
await page.nuxt.navigate('/store')
|
await page.nuxt.navigate('/store')
|
||||||
|
|
||||||
expect(await page.$text('h1')).toBe('Vuex Nested Modules')
|
expect(await page.$text('h1')).toBe('foo/bar/baz: Vuex Nested Modules')
|
||||||
expect(await page.$text('p')).toBe('1')
|
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 () => {
|
test('/head', async () => {
|
||||||
|
10
test/fixtures/basic/pages/store.vue
vendored
10
test/fixtures/basic/pages/store.vue
vendored
@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1>{{ baz }}</h1>
|
<h1>foo/bar/baz: {{ baz }}</h1>
|
||||||
<br>
|
<br>
|
||||||
<p>{{ $store.state.counter }}</p>
|
<h2>index/counter: {{ $store.state.counter }}</h2>
|
||||||
<br>
|
<br>
|
||||||
<h2>{{ getVal }}</h2>
|
<h3>foo/blarg/getVal: {{ getVal }}</h3>
|
||||||
<br>
|
<br>
|
||||||
<h3>{{ getBabVal }}</h3>
|
<h4>foo/bab/getBabVal: {{ getBabVal }}</h4>
|
||||||
|
<br>
|
||||||
|
<button @click="$store.commit('increment')">+1</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -70,8 +70,10 @@ describe('basic ssr', () => {
|
|||||||
|
|
||||||
test('/store', async () => {
|
test('/store', async () => {
|
||||||
const { html } = await nuxt.server.renderRoute('/store')
|
const { html } = await nuxt.server.renderRoute('/store')
|
||||||
expect(html).toContain('<h1>Vuex Nested Modules</h1>')
|
expect(html).toContain('<h1>foo/bar/baz: Vuex Nested Modules</h1>')
|
||||||
expect(html).toContain('<p>1</p>')
|
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 () => {
|
test('/head', async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user