From 40d52645e8db656c6a4e62aba5c3c89a2b158750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Tue, 28 Feb 2017 13:10:58 +0100 Subject: [PATCH] asyncData --- TODO.md | 10 +++++++- lib/app/client.js | 44 +++++++++++++++--------------------- lib/app/server.js | 26 +++++++++++++-------- lib/webpack/client.config.js | 4 +++- lib/webpack/server.config.js | 6 +++-- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/TODO.md b/TODO.md index b5ad3ca12b..475654d31d 100644 --- a/TODO.md +++ b/TODO.md @@ -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) diff --git a/lib/app/client.js b/lib/app/client.js index 8a3a1a739b..030013a4cc 100644 --- a/lib/app/client.js +++ b/lib/app/client.js @@ -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, '') - } + if (NUXT.serverRendered) { + Component.options.data = () => NUXT.data[index] if (Component._Ctor && Component._Ctor.options) { Component._Ctor.options.data = Component.options.data } diff --git a/lib/app/server.js b/lib/app/server.js index 241dd03cca..ee2dfdc21d 100644 --- a/lib/app/server.js +++ b/lib/app/server.js @@ -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.data && typeof Component.options.data === 'function') { - Component._data = Component.options.data - let promise = promisify(Component._data, ctx) - promise.then((data) => { + 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') { + 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' : '') %> diff --git a/lib/webpack/client.config.js b/lib/webpack/client.config.js index 6ea9ac2d27..0cb8066080 100644 --- a/lib/webpack/client.config.js +++ b/lib/webpack/client.config.js @@ -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({ diff --git a/lib/webpack/server.config.js b/lib/webpack/server.config.js index e8f1323f67..bcbbce1092 100644 --- a/lib/webpack/server.config.js +++ b/lib/webpack/server.config.js @@ -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 })) ]) })