diff --git a/src/server/create-renderer.js b/src/server/create-renderer.js index 502b6fa6d1d..6c7c8a41441 100644 --- a/src/server/create-renderer.js +++ b/src/server/create-renderer.js @@ -4,6 +4,7 @@ import RenderStream from './render-stream' import { createWriteFunction } from './write' import { createRenderFunction } from './render' import { createPromiseCallback } from './util' +import { isPromise } from '../shared/util' import TemplateRenderer from './template-renderer/index' import type { ClientManifest } from './template-renderer/index' @@ -33,6 +34,14 @@ export type RenderOptions = { runInNewContext?: boolean | 'once'; }; +function runRenderedCallback(context, component) { + if (!context || !context.rendered) { + return Promise.resolve(); + } + const result = context.rendered(context, component); + return isPromise(result) ? result : Promise.resolve(); +} + export function createRenderer ({ modules = [], directives = {}, @@ -85,26 +94,25 @@ export function createRenderer ({ if (err) { return cb(err) } - if (context && context.rendered) { - context.rendered(context) - } - if (template) { - try { - const res = templateRenderer.render(result, context) - if (typeof res !== 'string') { - // function template returning promise - res - .then(html => cb(null, html)) - .catch(cb) - } else { - cb(null, res) + runRenderedCallback(context, component).then(() => { + if (template) { + try { + const res = templateRenderer.render(result, context) + if (typeof res !== 'string') { + // function template returning promise + res + .then(html => cb(null, html)) + .catch(cb) + } else { + cb(null, res) + } + } catch (e) { + cb(e) } - } catch (e) { - cb(e) + } else { + cb(null, result) } - } else { - cb(null, result) - } + }) }) } catch (e) { cb(e) diff --git a/test/ssr/ssr-bundle-render.spec.js b/test/ssr/ssr-bundle-render.spec.js index ce7f8780a90..f968f37c037 100644 --- a/test/ssr/ssr-bundle-render.spec.js +++ b/test/ssr/ssr-bundle-render.spec.js @@ -84,6 +84,39 @@ function createAssertions (runInNewContext) { }) }) + it('renderToString calls context.rendered', done => { + createRenderer('app.js', { runInNewContext }, renderer => { + const rendered = jasmine.createSpy(); + const context = { url: '/test', rendered } + renderer.renderToString(context, () => { + expect(rendered).toHaveBeenCalledWith(context, jasmine.any(Object)) + expect(rendered.calls.mostRecent().args[1].constructor.name).toBe("Vue") + expect(rendered).toHaveBeenCalledTimes(1) + done() + }) + }) + }) + + it('renderToString waits if context.rendered returns a promise', done => { + createRenderer('app.js', { runInNewContext }, renderer => { + const rendered = (context) => { + return new Promise((resolve) => { + setTimeout(() => { + context.msg = 'Hello from context.rendered' + resolve() + }, 1000) + }) + } + const context = { url: '/test', rendered } + renderer.renderToString(context, (err, res) => { + expect(err).toBeNull() + expect(res).toBe('