mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
Fix asyncData on hot reloading
This commit is contained in:
parent
8253f5e75b
commit
b8727b8d51
1
TODO.md
1
TODO.md
@ -8,6 +8,7 @@ Tasks for `0.9.10`:
|
|||||||
- [ ] Fork preload-webpack-plugin and use it in package.json
|
- [ ] Fork preload-webpack-plugin and use it in package.json
|
||||||
- [ ] Test + Coverage performance, cache, filenames
|
- [ ] Test + Coverage performance, cache, filenames
|
||||||
- [ ] Manual tests on router.base & publicPath
|
- [ ] Manual tests on router.base & publicPath
|
||||||
|
- [ ] asyncData, fetch, transition, validate, scrollToTop can be in mixins and extend (super)
|
||||||
|
|
||||||
-> Not possible to have custom layout for a page, it should do the condition inside the layout itself (because of the middleware strategy)
|
-> Not possible to have custom layout for a page, it should do the condition inside the layout itself (because of the middleware strategy)
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ function fixPrepatch (to, ___) {
|
|||||||
// Set layout
|
// Set layout
|
||||||
this.setLayout(this.$options._nuxt.err ? NuxtError.layout : to.matched[0].components.default.options.layout)
|
this.setLayout(this.$options._nuxt.err ? NuxtError.layout : to.matched[0].components.default.options.layout)
|
||||||
// hot reloading
|
// hot reloading
|
||||||
hotReloadAPI(this)
|
Vue.nextTick(() => hotReloadAPI(this))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +224,8 @@ function fixPrepatch (to, ___) {
|
|||||||
function hotReloadAPI (_app) {
|
function hotReloadAPI (_app) {
|
||||||
if (!module.hot) return
|
if (!module.hot) return
|
||||||
const $nuxt = _app.$nuxt
|
const $nuxt = _app.$nuxt
|
||||||
|
if ($nuxt._hasHotReload) return
|
||||||
|
$nuxt._hasHotReload = true
|
||||||
var _forceUpdate = $nuxt.$forceUpdate.bind($nuxt)
|
var _forceUpdate = $nuxt.$forceUpdate.bind($nuxt)
|
||||||
$nuxt.$forceUpdate = function () {
|
$nuxt.$forceUpdate = function () {
|
||||||
let Component = getMatchedComponents(router.currentRoute)[0]
|
let Component = getMatchedComponents(router.currentRoute)[0]
|
||||||
@ -233,13 +235,15 @@ function hotReloadAPI (_app) {
|
|||||||
Component = Vue.extend(Component)
|
Component = Vue.extend(Component)
|
||||||
Component._Ctor = Component
|
Component._Ctor = Component
|
||||||
}
|
}
|
||||||
|
_app.error()
|
||||||
let promises = []
|
let promises = []
|
||||||
// If layout changed
|
// If layout changed
|
||||||
|
Component.options.layout = Component.options.layout || 'default'
|
||||||
if (_app.layoutName !== Component.options.layout) {
|
if (_app.layoutName !== Component.options.layout) {
|
||||||
let promise = _app.loadLayout(Component.options.layout)
|
let promise = _app.loadLayout(Component.options.layout)
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
_app.setLayout(Component.options.layout)
|
_app.setLayout(Component.options.layout)
|
||||||
hotReloadAPI(_app)
|
Vue.nextTick(() => hotReloadAPI(_app))
|
||||||
})
|
})
|
||||||
promises.push(promise)
|
promises.push(promise)
|
||||||
}
|
}
|
||||||
@ -248,37 +252,22 @@ function hotReloadAPI (_app) {
|
|||||||
router.push(path)
|
router.push(path)
|
||||||
}
|
}
|
||||||
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: _app.error })
|
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: _app.error })
|
||||||
// Check if data has been updated
|
// Call asyncData()
|
||||||
const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '')
|
let pAsyncData = promisify(Component.options.asyncData || noopData, context)
|
||||||
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
|
pAsyncData.then((asyncDataResult) => {
|
||||||
if (originalDataFn !== newDataFn) {
|
let data = (typeof Component.options.data === 'function' ? Component.options.data() : noopData())
|
||||||
Component._data = Component._Ctor.options.data || noopData
|
data = Object.assign(data, asyncDataResult)
|
||||||
let p = promisify(Component._data, context)
|
Component.options.data = () => data
|
||||||
p.then((data) => {
|
|
||||||
Component._cData = () => data || {}
|
|
||||||
Component.options.data = Component._cData
|
|
||||||
Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
|
|
||||||
Component._Ctor.options.data = Component.options.data
|
Component._Ctor.options.data = Component.options.data
|
||||||
<%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %>
|
<%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %>
|
||||||
})
|
})
|
||||||
promises.push(p)
|
promises.push(pAsyncData)
|
||||||
} else if (Component._cData) {
|
// Call fetch()
|
||||||
Component._data = Component.options.data
|
Component.options.fetch = Component.options.fetch || noopFetch
|
||||||
Component.options.data = Component._cData
|
let pFetch = Component.options.fetch(context)
|
||||||
Component._Ctor.options.data = Component.options.data
|
if (!(pFetch instanceof Promise)) { pFetch = Promise.resolve(pFetch) }
|
||||||
}
|
<%= (loading ? 'pFetch.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %>
|
||||||
// Check if fetch has been updated
|
promises.push(pFetch)
|
||||||
const originalFetchFn = (Component.options.fetch || noopFetch).toString().replace(/\s/g, '')
|
|
||||||
const newFetchFn = (Component._Ctor.options.fetch || noopFetch).toString().replace(/\s/g, '')
|
|
||||||
// Fetch has been updated, we call it to update the store
|
|
||||||
if (originalFetchFn !== newFetchFn) {
|
|
||||||
Component.options.fetch = Component._Ctor.options.fetch || noopFetch
|
|
||||||
let p = Component.options.fetch(context)
|
|
||||||
if (!(p instanceof Promise)) { p = Promise.resolve(p) }
|
|
||||||
<%= (loading ? 'p.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %>
|
|
||||||
promises.push(p)
|
|
||||||
}
|
|
||||||
if (!promises.length) return;
|
|
||||||
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
|
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
|
||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
|
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
|
||||||
@ -306,7 +295,13 @@ const resolveComponents = flatMapComponents(router.match(path), (Component, _, m
|
|||||||
Component.extendOptions = Component.options
|
Component.extendOptions = Component.options
|
||||||
}
|
}
|
||||||
if (NUXT.serverRendered) {
|
if (NUXT.serverRendered) {
|
||||||
Component.options.data = () => NUXT.data[index]
|
let data = {}
|
||||||
|
if (Component.options.data && typeof Component.options.data === 'function') {
|
||||||
|
data = Component.options.data()
|
||||||
|
}
|
||||||
|
// Merge data() and asyncData() results
|
||||||
|
data = Object.assign(data, NUXT.data[index])
|
||||||
|
Component.options.data = () => data
|
||||||
if (Component._Ctor && Component._Ctor.options) {
|
if (Component._Ctor && Component._Ctor.options) {
|
||||||
Component._Ctor.options.data = Component.options.data
|
Component._Ctor.options.data = Component.options.data
|
||||||
}
|
}
|
||||||
@ -346,10 +341,12 @@ Promise.all(resolveComponents)
|
|||||||
.then(({ _app, Components }) => {
|
.then(({ _app, Components }) => {
|
||||||
const mountApp = () => {
|
const mountApp = () => {
|
||||||
_app.$mount('#__nuxt')
|
_app.$mount('#__nuxt')
|
||||||
|
Vue.nextTick(() => {
|
||||||
// Hot reloading
|
// Hot reloading
|
||||||
hotReloadAPI(_app)
|
hotReloadAPI(_app)
|
||||||
// Call window.onNuxtReady callbacks
|
// Call window.onNuxtReady callbacks
|
||||||
Vue.nextTick(() => nuxtReady(_app))
|
nuxtReady(_app)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
<% if (store) { %>
|
<% if (store) { %>
|
||||||
// Replace store state
|
// Replace store state
|
||||||
|
@ -133,14 +133,18 @@ export default context => {
|
|||||||
Component._Ctor.options.data = Component.options.data
|
Component._Ctor.options.data = Component.options.data
|
||||||
})
|
})
|
||||||
promises.push(promise)
|
promises.push(promise)
|
||||||
|
} else {
|
||||||
|
promises.push(null)
|
||||||
}
|
}
|
||||||
if (Component.options.fetch) {
|
if (Component.options.fetch) {
|
||||||
promises.push(Component.options.fetch(ctx))
|
promises.push(Component.options.fetch(ctx))
|
||||||
|
} else {
|
||||||
|
promises.push(null)
|
||||||
}
|
}
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
if (!Components.length) {
|
if (!Components.length) {
|
||||||
context.nuxt.error = context.error({ statusCode: 404, message: 'This page could not be found.' })
|
context.nuxt.error = context.error({ statusCode: 404, message: 'This page could not be found.' })
|
||||||
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
||||||
@ -150,9 +154,7 @@ export default context => {
|
|||||||
debug('Data fetching ' + context.req.url + ': ' + (Date.now() - s) + 'ms')
|
debug('Data fetching ' + context.req.url + ': ' + (Date.now() - s) + 'ms')
|
||||||
<% } %>
|
<% } %>
|
||||||
// datas are the first row of each
|
// datas are the first row of each
|
||||||
context.nuxt.data = Components.map((Component) => {
|
context.nuxt.data = res.map((r) => (r[0] || {}))
|
||||||
return (typeof Component.options.data === 'function' ? Component.options.data() : {})
|
|
||||||
})
|
|
||||||
context.nuxt.error = _app.$options._nuxt.err
|
context.nuxt.error = _app.$options._nuxt.err
|
||||||
<%= (store ? '// Add the state from the vuex store' : '') %>
|
<%= (store ? '// Add the state from the vuex store' : '') %>
|
||||||
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
||||||
|
Loading…
Reference in New Issue
Block a user