ssr: repeat all test cases for directMode

This commit is contained in:
Evan You 2017-04-14 16:26:12 +08:00
parent 760a74480e
commit 5eeb9de5e7
3 changed files with 89 additions and 69 deletions

View File

@ -92,30 +92,33 @@ export function createBundleRunner (entry, files, basedir, direct) {
// default mode: creates a fresh context and re-evaluate the bundle
// on each render. Ensures entire application state is fresh for each
// render, but incurs extra evaluation cost.
return (_context = {}) => new Promise((resolve, reject) => {
_context._registeredComponents = new Set()
const res = evaluate(entry, createContext(_context))
resolve(typeof res === 'function' ? res(_context) : res)
return (userContext = {}) => new Promise(resolve => {
userContext._registeredComponents = new Set()
const res = evaluate(entry, createContext(userContext))
resolve(typeof res === 'function' ? res(userContext) : res)
})
} else {
// direct mode: instead of re-evaluating the whole bundle on
// each render, it simply calls the exported function. This avoids the
// module evaluation costs but requires the source code to be structured
// slightly differently.
const initialExposedContext = {}
const context = createContext(initialExposedContext)
const runner = evaluate(entry, context)
if (typeof runner !== 'function') {
throw new Error('direct mode expects bundle export to be a function.')
}
return (_context = {}) => {
context.__VUE_SSR_CONTEXT__ = _context
_context._registeredComponents = new Set()
// vue-style-loader styles imported outside of component lifecycle hooks
if (initialExposedContext._styles) {
_context._styles = deepClone(initialExposedContext._styles)
const initialContext = {}
const sharedContext = createContext(initialContext)
let runner // lazy creation so that errors can be caught by user
return (userContext = {}) => new Promise(resolve => {
if (!runner) {
runner = evaluate(entry, sharedContext)
if (typeof runner !== 'function') {
throw new Error('direct mode expects bundle export to be a function.')
}
}
return runner(_context)
}
sharedContext.__VUE_SSR_CONTEXT__ = userContext
userContext._registeredComponents = new Set()
// vue-style-loader styles imported outside of component lifecycle hooks
if (initialContext._styles) {
userContext._styles = deepClone(initialContext._styles)
}
resolve(runner(userContext))
})
}
}

View File

@ -33,8 +33,13 @@ export function createRenderer (file, options, cb) {
}
describe('SSR: bundle renderer', () => {
createAssertions(true)
createAssertions(false)
})
function createAssertions (directMode) {
it('renderToString', done => {
createRenderer('app.js', renderer => {
createRenderer('app.js', { directMode }, renderer => {
const context = { url: '/test' }
renderer.renderToString(context, (err, res) => {
expect(err).toBeNull()
@ -46,7 +51,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToStream', done => {
createRenderer('app.js', renderer => {
createRenderer('app.js', { directMode }, renderer => {
const context = { url: '/test' }
const stream = renderer.renderToStream(context)
let res = ''
@ -62,7 +67,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToString catch error', done => {
createRenderer('error.js', renderer => {
createRenderer('error.js', { directMode }, renderer => {
renderer.renderToString(err => {
expect(err.message).toBe('foo')
done()
@ -71,7 +76,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToStream catch error', done => {
createRenderer('error.js', renderer => {
createRenderer('error.js', { directMode }, renderer => {
const stream = renderer.renderToStream()
stream.on('error', err => {
expect(err.message).toBe('foo')
@ -85,6 +90,7 @@ describe('SSR: bundle renderer', () => {
const get = jasmine.createSpy('get')
const set = jasmine.createSpy('set')
const options = {
directMode,
cache: {
// async
get: (key, cb) => {
@ -127,6 +133,7 @@ describe('SSR: bundle renderer', () => {
const get = jasmine.createSpy('get')
const set = jasmine.createSpy('set')
const options = {
directMode,
cache: {
// async
has: (key, cb) => {
@ -172,7 +179,10 @@ describe('SSR: bundle renderer', () => {
const cache = LRU({ maxAge: Infinity })
spyOn(cache, 'get').and.callThrough()
spyOn(cache, 'set').and.callThrough()
const options = { cache }
const options = {
cache,
directMode
}
createRenderer('nested-cache.js', options, renderer => {
const expected = '<div data-server-rendered="true">/test</div>'
const key = 'app::1'
@ -203,7 +213,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToString (bundle format with code split)', done => {
createRenderer('split.js', { asBundle: true }, renderer => {
createRenderer('split.js', { directMode, asBundle: true }, renderer => {
const context = { url: '/test' }
renderer.renderToString(context, (err, res) => {
expect(err).toBeNull()
@ -214,7 +224,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToStream (bundle format with code split)', done => {
createRenderer('split.js', { asBundle: true }, renderer => {
createRenderer('split.js', { directMode, asBundle: true }, renderer => {
const context = { url: '/test' }
const stream = renderer.renderToStream(context)
let res = ''
@ -229,7 +239,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToString catch error (bundle format with source map)', done => {
createRenderer('error.js', { asBundle: true }, renderer => {
createRenderer('error.js', { directMode, asBundle: true }, renderer => {
renderer.renderToString(err => {
expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')
expect(err.message).toBe('foo')
@ -239,7 +249,7 @@ describe('SSR: bundle renderer', () => {
})
it('renderToString catch error (bundle format with source map)', done => {
createRenderer('error.js', { asBundle: true }, renderer => {
createRenderer('error.js', { directMode, asBundle: true }, renderer => {
const stream = renderer.renderToStream()
stream.on('error', err => {
expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')
@ -248,4 +258,4 @@ describe('SSR: bundle renderer', () => {
})
})
})
})
}

View File

@ -169,56 +169,63 @@ describe('SSR: template option', () => {
`<script src="/main.js"></script>` +
`</body></html>`
it('bundleRenderer + renderToString + clientManifest', done => {
createRendererWithManifest('split.js', renderer => {
renderer.renderToString({}, (err, res) => {
expect(err).toBeNull()
expect(res).toContain(expectedHTMLWithManifest(false))
done()
createClientManifestAssertions(true)
createClientManifestAssertions(false)
function createClientManifestAssertions (directMode) {
it('bundleRenderer + renderToString + clientManifest', done => {
createRendererWithManifest('split.js', { directMode }, renderer => {
renderer.renderToString({}, (err, res) => {
expect(err).toBeNull()
expect(res).toContain(expectedHTMLWithManifest(false))
done()
})
})
})
})
it('bundleRenderer + renderToStream + clientManifest + shouldPreload', done => {
createRendererWithManifest('split.js', {
shouldPreload: (file, type) => {
if (type === 'image' || type === 'script' || type === 'font') {
return true
it('bundleRenderer + renderToStream + clientManifest + shouldPreload', done => {
createRendererWithManifest('split.js', {
directMode,
shouldPreload: (file, type) => {
if (type === 'image' || type === 'script' || type === 'font') {
return true
}
}
}
}, renderer => {
const stream = renderer.renderToStream({})
let res = ''
stream.on('data', chunk => {
res += chunk.toString()
})
stream.on('end', () => {
expect(res).toContain(expectedHTMLWithManifest(true))
done()
}, renderer => {
const stream = renderer.renderToStream({})
let res = ''
stream.on('data', chunk => {
res += chunk.toString()
})
stream.on('end', () => {
expect(res).toContain(expectedHTMLWithManifest(true))
done()
})
})
})
})
it('bundleRenderer + renderToString + clientManifest + no template', done => {
createRendererWithManifest('split.js', {
template: null
}, renderer => {
const context = {}
renderer.renderToString(context, (err, res) => {
expect(err).toBeNull()
it('bundleRenderer + renderToString + clientManifest + no template', done => {
createRendererWithManifest('split.js', {
directMode,
template: null
}, renderer => {
const context = {}
renderer.renderToString(context, (err, res) => {
expect(err).toBeNull()
const customOutput =
`<html><head>${
context.renderPreloadLinks() +
context.renderPrefetchLinks()
}</head><body>${
res +
context.renderScripts()
}</body></html>`
const customOutput =
`<html><head>${
context.renderPreloadLinks() +
context.renderPrefetchLinks()
}</head><body>${
res +
context.renderScripts()
}</body></html>`
expect(customOutput).toContain(expectedHTMLWithManifest(false))
done()
expect(customOutput).toContain(expectedHTMLWithManifest(false))
done()
})
})
})
})
}
})