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
|
||||
- [ ] Test + Coverage performance, cache, filenames
|
||||
- [ ] 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)
|
||||
|
||||
|
@ -216,7 +216,7 @@ function fixPrepatch (to, ___) {
|
||||
// Set layout
|
||||
this.setLayout(this.$options._nuxt.err ? NuxtError.layout : to.matched[0].components.default.options.layout)
|
||||
// hot reloading
|
||||
hotReloadAPI(this)
|
||||
Vue.nextTick(() => hotReloadAPI(this))
|
||||
})
|
||||
}
|
||||
|
||||
@ -224,6 +224,8 @@ function fixPrepatch (to, ___) {
|
||||
function hotReloadAPI (_app) {
|
||||
if (!module.hot) return
|
||||
const $nuxt = _app.$nuxt
|
||||
if ($nuxt._hasHotReload) return
|
||||
$nuxt._hasHotReload = true
|
||||
var _forceUpdate = $nuxt.$forceUpdate.bind($nuxt)
|
||||
$nuxt.$forceUpdate = function () {
|
||||
let Component = getMatchedComponents(router.currentRoute)[0]
|
||||
@ -233,13 +235,15 @@ function hotReloadAPI (_app) {
|
||||
Component = Vue.extend(Component)
|
||||
Component._Ctor = Component
|
||||
}
|
||||
_app.error()
|
||||
let promises = []
|
||||
// If layout changed
|
||||
Component.options.layout = Component.options.layout || 'default'
|
||||
if (_app.layoutName !== Component.options.layout) {
|
||||
let promise = _app.loadLayout(Component.options.layout)
|
||||
promise.then(() => {
|
||||
_app.setLayout(Component.options.layout)
|
||||
hotReloadAPI(_app)
|
||||
Vue.nextTick(() => hotReloadAPI(_app))
|
||||
})
|
||||
promises.push(promise)
|
||||
}
|
||||
@ -248,37 +252,22 @@ function hotReloadAPI (_app) {
|
||||
router.push(path)
|
||||
}
|
||||
const context = getContext({ route: router.currentRoute<%= (store ? ', store' : '') %>, isClient: true, next: next.bind(this), error: _app.error })
|
||||
// Check if data has been updated
|
||||
const originalDataFn = (Component._data || noopData).toString().replace(/\s/g, '')
|
||||
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
|
||||
if (originalDataFn !== newDataFn) {
|
||||
Component._data = Component._Ctor.options.data || noopData
|
||||
let p = promisify(Component._data, context)
|
||||
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
|
||||
<%= (loading ? 'this.$loading.increase && this.$loading.increase(30)' : '') %>
|
||||
})
|
||||
promises.push(p)
|
||||
} else if (Component._cData) {
|
||||
Component._data = Component.options.data
|
||||
Component.options.data = Component._cData
|
||||
// Call asyncData()
|
||||
let pAsyncData = promisify(Component.options.asyncData || noopData, context)
|
||||
pAsyncData.then((asyncDataResult) => {
|
||||
let data = (typeof Component.options.data === 'function' ? Component.options.data() : noopData())
|
||||
data = Object.assign(data, asyncDataResult)
|
||||
Component.options.data = () => data
|
||||
Component._Ctor.options.data = Component.options.data
|
||||
}
|
||||
// Check if fetch has been updated
|
||||
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.increase && this.$loading.increase(30)' : '') %>
|
||||
})
|
||||
promises.push(pAsyncData)
|
||||
// Call fetch()
|
||||
Component.options.fetch = Component.options.fetch || noopFetch
|
||||
let pFetch = Component.options.fetch(context)
|
||||
if (!(pFetch instanceof Promise)) { pFetch = Promise.resolve(pFetch) }
|
||||
<%= (loading ? 'pFetch.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %>
|
||||
promises.push(pFetch)
|
||||
<%= (loading ? 'this.$loading.start && this.$loading.start()' : '') %>
|
||||
return Promise.all(promises).then(() => {
|
||||
<%= (loading ? 'this.$loading.finish && this.$loading.finish()' : '') %>
|
||||
@ -306,7 +295,13 @@ const resolveComponents = flatMapComponents(router.match(path), (Component, _, m
|
||||
Component.extendOptions = Component.options
|
||||
}
|
||||
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) {
|
||||
Component._Ctor.options.data = Component.options.data
|
||||
}
|
||||
@ -346,10 +341,12 @@ Promise.all(resolveComponents)
|
||||
.then(({ _app, Components }) => {
|
||||
const mountApp = () => {
|
||||
_app.$mount('#__nuxt')
|
||||
// Hot reloading
|
||||
hotReloadAPI(_app)
|
||||
// Call window.onNuxtReady callbacks
|
||||
Vue.nextTick(() => nuxtReady(_app))
|
||||
Vue.nextTick(() => {
|
||||
// Hot reloading
|
||||
hotReloadAPI(_app)
|
||||
// Call window.onNuxtReady callbacks
|
||||
nuxtReady(_app)
|
||||
})
|
||||
}
|
||||
<% if (store) { %>
|
||||
// Replace store state
|
||||
|
@ -133,14 +133,18 @@ export default context => {
|
||||
Component._Ctor.options.data = Component.options.data
|
||||
})
|
||||
promises.push(promise)
|
||||
} else {
|
||||
promises.push(null)
|
||||
}
|
||||
if (Component.options.fetch) {
|
||||
promises.push(Component.options.fetch(ctx))
|
||||
} else {
|
||||
promises.push(null)
|
||||
}
|
||||
return Promise.all(promises)
|
||||
}))
|
||||
})
|
||||
.then(() => {
|
||||
.then((res) => {
|
||||
if (!Components.length) {
|
||||
context.nuxt.error = context.error({ statusCode: 404, message: 'This page could not be found.' })
|
||||
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
||||
@ -150,9 +154,7 @@ export default context => {
|
||||
debug('Data fetching ' + context.req.url + ': ' + (Date.now() - s) + 'ms')
|
||||
<% } %>
|
||||
// datas are the first row of each
|
||||
context.nuxt.data = Components.map((Component) => {
|
||||
return (typeof Component.options.data === 'function' ? Component.options.data() : {})
|
||||
})
|
||||
context.nuxt.data = res.map((r) => (r[0] || {}))
|
||||
context.nuxt.error = _app.$options._nuxt.err
|
||||
<%= (store ? '// Add the state from the vuex store' : '') %>
|
||||
<%= (store ? 'context.nuxt.state = store.state' : '') %>
|
||||
|
Loading…
Reference in New Issue
Block a user