asyncData

This commit is contained in:
Sébastien Chopin 2017-02-28 13:10:58 +01:00
parent 996613ce8b
commit 40d52645e8
5 changed files with 51 additions and 39 deletions

10
TODO.md
View File

@ -4,8 +4,16 @@ Tasks for `0.9.10`:
- [x] Add expired headers (production)
- [x] Activate layout only on afterEach #214
- [x] Custom layout in layouts/error.vue #172
- [x] Add Doc for build.filenames, performance.gzip and performance.prefetch
- [ ] Fork preload-webpack-plugin and use it in package.json
- [ ] Test + Coverage performance, cache, filenames
- [ ] Manual tests on router.base & publicPath
- [ ] Add Doc for build.filenames, performance.gzip and performance.prefetch
-> Not possible to have custom layout for a page, it should do the condition inside the layout itself (because of the middleware strategy)
Release:
## Deprecated
- `process.BROWSER_BUILD` is deprecated in favour of `process.browser` (`BROWSER_BUILD` will be removed for the 1.0)
- `process.SERVER_BUILD` is deprecated in favour of `process.server` (`SERVER_BUILD` will be removed for the 1.0)

View File

@ -98,20 +98,9 @@ function render (to, from, next) {
}
// Update ._data and other properties if hot reloaded
Components.forEach(function (Component) {
if (!Component._data) {
Component._data = Component.options.data || noopData
}
if (Component._Ctor && Component._Ctor.options) {
Component.options.asyncData = Component._Ctor.options.asyncData
Component.options.fetch = Component._Ctor.options.fetch
if (Component._dataFn) {
const originalDataFn = Component._data.toString().replace(/\s/g, '')
const dataFn = Component._dataFn
const newDataFn = (Component._Ctor.options.data || noopData).toString().replace(/\s/g, '')
// If component data method changed
if (newDataFn !== originalDataFn && newDataFn !== dataFn) {
Component._data = Component._Ctor.options.data || noopData
}
}
}
})
this.setTransitions(mapTransitions(Components, to, from))
@ -141,13 +130,21 @@ function render (to, from, next) {
return Promise.resolve()
}
let promises = []
// Validate method
if (Component._data && typeof Component._data === 'function') {
var promise = promisify(Component._data, context)
promise.then((data) => {
Component._cData = () => data || {}
Component.options.data = Component._cData
Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
// asyncData method
if (Component.options.asyncData && typeof Component.options.asyncData === 'function') {
var promise = promisify(Component.options.asyncData, context)
promise.then((asyncDataResult) => {
let data = {}
// keep asyncData() result
Component._asyncDataResult = asyncDataResult
// Call data() if defined
if (Component.options.data && typeof Component.options.data === 'function') {
data = Component.options.data()
}
// Merge data() and asyncData() results
data = Object.assign(data, asyncDataResult)
// Overwrite .data() method with merged data
Component.options.data = () => data
if (Component._Ctor && Component._Ctor.options) {
Component._Ctor.options.data = Component.options.data
}
@ -308,13 +305,8 @@ const resolveComponents = flatMapComponents(router.match(path), (Component, _, m
Component._Ctor = Component
Component.extendOptions = Component.options
}
if (Component.options.data && typeof Component.options.data === 'function') {
Component._data = Component.options.data
if (NUXT.serverRendered) {
Component._cData = () => NUXT.data[index] || {}
Component.options.data = Component._cData
Component._dataFn = Component.options.data.toString().replace(/\s/g, '')
}
Component.options.data = () => NUXT.data[index]
if (Component._Ctor && Component._Ctor.options) {
Component._Ctor.options.data = Component.options.data
}

View File

@ -3,6 +3,7 @@
const debug = require('debug')('nuxt:render')
debug.color = 4 // force blue color
import Vue from 'vue'
import { stringify } from 'querystring'
import { omit } from 'lodash'
import middleware from './middleware'
@ -114,19 +115,24 @@ export default context => {
Components = []
return _app
}
// Call data & fetch hooks on components matched by the route.
// Call asyncData & fetch hooks on components matched by the route.
return Promise.all(Components.map((Component) => {
let promises = []
if (Component.options.asyncData && typeof Component.options.asyncData === 'function') {
let promise = promisify(Component.options.asyncData, ctx)
// Call asyncData(context)
promise.then((asyncDataResult) => {
let data = {}
// Call data() if defined
if (Component.options.data && typeof Component.options.data === 'function') {
Component._data = Component.options.data
let promise = promisify(Component._data, ctx)
promise.then((data) => {
data = Component.options.data()
}
// Merge data() and asyncData() results
data = Object.assign(data, asyncDataResult)
Component.options.data = () => data
Component._Ctor.options.data = Component.options.data
})
promises.push(promise)
} else {
promises.push(null)
}
if (Component.options.fetch) {
promises.push(Component.options.fetch(ctx))
@ -134,7 +140,7 @@ export default context => {
return Promise.all(promises)
}))
})
.then((res) => {
.then(() => {
if (!Components.length) {
context.nuxt.error = context.error({ statusCode: 404, message: 'This page could not be found.' })
<%= (store ? 'context.nuxt.state = store.state' : '') %>
@ -144,7 +150,9 @@ export default context => {
debug('Data fetching ' + context.req.url + ': ' + (Date.now() - s) + 'ms')
<% } %>
// datas are the first row of each
context.nuxt.data = res.map((tab) => tab[0])
context.nuxt.data = Components.map((Component) => {
return (typeof Component.options.data === 'function' ? Component.options.data() : {})
})
context.nuxt.error = _app.$options._nuxt.err
<%= (store ? '// Add the state from the vuex store' : '') %>
<%= (store ? 'context.nuxt.state = store.state' : '') %>

View File

@ -47,7 +47,9 @@ export default function () {
new webpack.DefinePlugin(Object.assign(env, {
'process.env.NODE_ENV': JSON.stringify(this.dev ? 'development' : 'production'),
'process.BROWSER_BUILD': true,
'process.SERVER_BUILD': false
'process.SERVER_BUILD': false,
'process.browser': true,
'process.server': true
})),
// Extract vendor chunks for better caching
new webpack.optimize.CommonsChunkPlugin({

View File

@ -32,8 +32,10 @@ export default function () {
plugins: (config.plugins || []).concat([
new webpack.DefinePlugin(Object.assign(env, {
'process.env.NODE_ENV': JSON.stringify(this.dev ? 'development' : 'production'),
'process.BROWSER_BUILD': false,
'process.SERVER_BUILD': true
'process.BROWSER_BUILD': false, // deprecated
'process.SERVER_BUILD': true, // deprecated
'process.browser': false,
'process.server': true
}))
])
})