Add beforeNuxtRender hook

This commit is contained in:
Sebastien Chopin 2017-07-27 16:26:59 +02:00
parent 6c6e6e55aa
commit 4a6b651d56
3 changed files with 23 additions and 16 deletions

View File

@ -113,6 +113,7 @@ async function createApp (ssrContext) {
<% if(store) { %>store,<% } %> <% if(store) { %>store,<% } %>
req: ssrContext ? ssrContext.req : undefined, req: ssrContext ? ssrContext.req : undefined,
res: ssrContext ? ssrContext.res : undefined, res: ssrContext ? ssrContext.res : undefined,
beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined
}, app) }, app)
<% plugins.filter(p => p.ssr).forEach(plugin => { %> <% plugins.filter(p => p.ssr).forEach(plugin => { %>

View File

@ -45,27 +45,28 @@ export default async context => {
// Create context.next for simulate next() of beforeEach() when wanted to redirect // Create context.next for simulate next() of beforeEach() when wanted to redirect
context.redirected = false context.redirected = false
context.next = createNext(context) context.next = createNext(context)
context.beforeRenderFns = []
const { app, router<%= (store ? ', store' : '') %> } = await createApp(context) const { app, router<%= (store ? ', store' : '') %> } = await createApp(context)
const _app = new Vue(app) const _app = new Vue(app)
<% if (store) { %> <% if (store) { %>
// Add store to the context // Add store to the context
context.store = store context.store = store
<% } %> <% } %>
// Add route to the context // Add route to the context
context.route = router.currentRoute context.route = router.currentRoute
// Nuxt object // Nuxt object
context.nuxt = { layout: 'default', data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } context.nuxt = { layout: 'default', data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true }
// Add meta infos // Add meta infos
context.meta = _app.$meta() context.meta = _app.$meta()
// Error function // Error function
context.error = _app.$options._nuxt.error.bind(_app) context.error = _app.$options._nuxt.error.bind(_app)
// Keep asyncData for each matched component in context // Keep asyncData for each matched component in context
context.asyncData = {} context.asyncData = {}
@ -73,8 +74,8 @@ export default async context => {
const ctx = getContext(context, app) const ctx = getContext(context, app)
<% if (isDev) { %>const s = isDev && Date.now()<% } %> <% if (isDev) { %>const s = isDev && Date.now()<% } %>
// Resolve components // Resolve components
let Components = [] let Components = []
try { try {
Components = await Promise.all(getMatchedComponents(router.match(context.url)).map(Component => { Components = await Promise.all(getMatchedComponents(router.match(context.url)).map(Component => {
@ -118,7 +119,7 @@ export default async context => {
layout = _app.setLayout(layout) layout = _app.setLayout(layout)
// ...Set layout to __NUXT__ // ...Set layout to __NUXT__
context.nuxt.layout = _app.layoutName context.nuxt.layout = _app.layoutName
// Call middleware (layout + pages) // Call middleware (layout + pages)
if (!context.nuxt.error) { if (!context.nuxt.error) {
midd = [] midd = []
@ -134,9 +135,9 @@ export default async context => {
} }
return middleware[name] return middleware[name]
}) })
await middlewareSeries(midd, ctx) await middlewareSeries(midd, ctx)
// If there is a redirect // If there is a redirect
if (context.redirected) return noopApp() if (context.redirected) return noopApp()
} }
@ -161,11 +162,11 @@ export default async context => {
// Call the 404 error by making the Components array empty // Call the 404 error by making the Components array empty
Components = [] Components = []
} }
// Call asyncData & fetch hooks on components matched by the route. // Call asyncData & fetch hooks on components matched by the route.
let asyncDatas = await Promise.all(Components.map(Component => { let asyncDatas = await Promise.all(Components.map(Component => {
let promises = [] let promises = []
// Call asyncData(context) // Call asyncData(context)
if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { if (Component.options.asyncData && typeof Component.options.asyncData === 'function') {
let promise = promisify(Component.options.asyncData, ctx) let promise = promisify(Component.options.asyncData, ctx)
@ -189,7 +190,7 @@ export default async context => {
return Promise.all(promises) return Promise.all(promises)
})) }))
// If no Components found, returns 404 // If no Components found, returns 404
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.' })
@ -210,6 +211,8 @@ export default async context => {
context.nuxt.state = store.state context.nuxt.state = store.state
<% } %> <% } %>
await Promise.all(context.beforeRenderFns.map((fn) => promisify(fn, { Components, nuxtState: context.nuxt })))
// If no error, return main app // If no error, return main app
if (!context.nuxt.error) { if (!context.nuxt.error) {
return _app return _app
@ -220,6 +223,6 @@ export default async context => {
context.nuxt.layout = layout || '' context.nuxt.layout = layout || ''
await _app.loadLayout(layout) await _app.loadLayout(layout)
_app.setLayout(layout) _app.setLayout(layout)
return _app return _app
} }

View File

@ -104,6 +104,9 @@ export function getContext (context, app) {
if (context.req) ctx.req = context.req if (context.req) ctx.req = context.req
if (context.res) ctx.res = context.res if (context.res) ctx.res = context.res
if (context.from) ctx.from = context.from if (context.from) ctx.from = context.from
if (ctx.isServer && context.beforeRenderFns) {
ctx.beforeNuxtRender = (fn) => context.beforeRenderFns.push(fn)
}
return ctx return ctx
} }