Skip to content

Commit c2c8741

Browse files
committed
test bundleRenderer bundle format support + source map
1 parent a2ca9b5 commit c2c8741

File tree

8 files changed

+137
-30
lines changed

8 files changed

+137
-30
lines changed

Diff for: .babelrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"presets": ["es2015", "flow-vue"],
3-
"plugins": ["transform-vue-jsx"],
3+
"plugins": ["transform-vue-jsx", "syntax-dynamic-import"],
44
"ignore": [
55
"dist/*.js",
66
"packages/**/*.js"

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"babel-helper-vue-jsx-merge-props": "^2.0.2",
6565
"babel-loader": "^6.2.4",
6666
"babel-plugin-istanbul": "^3.0.0",
67+
"babel-plugin-syntax-dynamic-import": "^6.18.0",
6768
"babel-plugin-syntax-jsx": "^6.18.0",
6869
"babel-plugin-transform-vue-jsx": "^3.2.0",
6970
"babel-preset-es2015": "^6.9.0",
@@ -110,10 +111,10 @@
110111
"selenium-server": "^2.53.1",
111112
"typescript": "^2.0.9",
112113
"uglify-js": "^2.6.2",
114+
"vue-ssr-webpack-plugin": "^1.0.0",
113115
"webpack": "^2.2.0",
114116
"weex-js-runtime": "^0.17.0-alpha4",
115117
"weex-vdom-tester": "^0.1.4"
116118
},
117-
"dependencies": {},
118119
"unpkg": "dist/vue.js"
119120
}

Diff for: src/server/create-bundle-renderer.js

+22-17
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,36 @@ export function createBundleRendererCreator (createRenderer: () => Renderer) {
4747
cb = context
4848
context = {}
4949
}
50-
runInVm(entry, files, context).then(app => {
51-
renderer.renderToString(app, cb)
52-
}).catch(err => {
53-
if (err instanceof Error) {
54-
rewriteErrorTrace(err, maps)
55-
}
50+
runInVm(entry, files, context).catch(err => {
51+
rewriteErrorTrace(err, maps)
5652
cb(err)
53+
}).then(app => {
54+
if (app) {
55+
renderer.renderToString(app, (err, res) => {
56+
rewriteErrorTrace(err, maps)
57+
cb(err, res)
58+
})
59+
}
5760
})
5861
},
5962
renderToStream: (context?: Object) => {
6063
const res = new PassThrough()
61-
runInVm(entry, files, context).then(app => {
62-
const renderStream = renderer.renderToStream(app)
63-
renderStream.on('error', err => {
64-
rewriteErrorTrace(err, maps)
65-
res.emit('error', err)
66-
})
67-
renderStream.pipe(res)
68-
}).catch(err => {
64+
runInVm(entry, files, context).catch(err => {
65+
rewriteErrorTrace(err, maps)
66+
// avoid emitting synchronously before user can
67+
// attach error listener
6968
process.nextTick(() => {
70-
if (err instanceof Error) {
71-
rewriteErrorTrace(err, maps)
72-
}
7369
res.emit('error', err)
7470
})
71+
}).then(app => {
72+
if (app) {
73+
const renderStream = renderer.renderToStream(app)
74+
renderStream.on('error', err => {
75+
rewriteErrorTrace(err, maps)
76+
res.emit('error', err)
77+
})
78+
renderStream.pipe(res)
79+
}
7580
})
7681
return res
7782
}

Diff for: src/server/source-map-support.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ export function createSourceMapConsumers (rawMaps: Object) {
1212
return maps
1313
}
1414

15-
export function rewriteErrorTrace (e: Error, mapConsumers: {
15+
export function rewriteErrorTrace (e: any, mapConsumers: {
1616
[key: string]: SourceMapConsumer
1717
}) {
18-
e.stack = e.stack.split('\n').map(line => {
19-
return rewriteTraceLine(line, mapConsumers)
20-
}).join('\n')
18+
if (e && typeof e.stack === 'string') {
19+
e.stack = e.stack.split('\n').map(line => {
20+
return rewriteTraceLine(line, mapConsumers)
21+
}).join('\n')
22+
}
2123
}
2224

2325
function rewriteTraceLine (trace: string, mapConsumers: {

Diff for: test/ssr/fixtures/comp.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
render (h) {
3+
return h('div', 'async')
4+
}
5+
}

Diff for: test/ssr/fixtures/split.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Vue from '../../../dist/vue.runtime.common.js'
2+
3+
// async component!
4+
const Foo = () => import('./comp')
5+
6+
export default context => {
7+
return new Promise(resolve => {
8+
context.msg = 'hello'
9+
const vm = new Vue({
10+
render (h) {
11+
return h('div', [
12+
context.url,
13+
h(Foo)
14+
])
15+
}
16+
})
17+
18+
// simulate router.onReady
19+
Foo().then(comp => {
20+
// resolve now to make the render sync
21+
Foo.resolved = Vue.extend(comp)
22+
resolve(vm)
23+
})
24+
})
25+
}

Diff for: test/ssr/ssr-bundle-render.spec.js

+66-5
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,46 @@
11
import path from 'path'
22
import webpack from 'webpack'
33
import MemoeryFS from 'memory-fs'
4+
import VueSSRPlugin from 'vue-ssr-webpack-plugin'
45
import { createBundleRenderer } from '../../packages/vue-server-renderer'
56

67
const rendererCache = {}
78
function createRenderer (file, cb, options) {
89
if (!options && rendererCache[file]) {
910
return cb(rendererCache[file])
1011
}
11-
const compiler = webpack({
12+
13+
const asBundle = !!(options && options.asBundle)
14+
if (options) delete options.asBundle
15+
16+
const config = {
1217
target: 'node',
1318
entry: path.resolve(__dirname, 'fixtures', file),
19+
devtool: asBundle ? '#source-map' : false,
1420
output: {
1521
path: '/',
1622
filename: 'bundle.js',
1723
libraryTarget: 'commonjs2'
1824
},
1925
module: {
2026
rules: [{ test: /\.js$/, loader: 'babel-loader' }]
21-
}
22-
})
27+
},
28+
plugins: asBundle
29+
? [new VueSSRPlugin()]
30+
: []
31+
}
32+
33+
const compiler = webpack(config)
2334
const fs = new MemoeryFS()
2435
compiler.outputFileSystem = fs
36+
2537
compiler.run((err, stats) => {
2638
expect(err).toBeFalsy()
2739
expect(stats.errors).toBeFalsy()
28-
const code = fs.readFileSync('/bundle.js', 'utf-8')
29-
const renderer = rendererCache[file] = createBundleRenderer(code, options)
40+
const bundle = asBundle
41+
? JSON.parse(fs.readFileSync('/vue-ssr-bundle.json', 'utf-8'))
42+
: fs.readFileSync('/bundle.js', 'utf-8')
43+
const renderer = rendererCache[file] = createBundleRenderer(bundle, options)
3044
cb(renderer)
3145
})
3246
}
@@ -162,4 +176,51 @@ describe('SSR: bundle renderer', () => {
162176
})
163177
}, options)
164178
})
179+
180+
it('renderToString (bundle format with code split)', done => {
181+
createRenderer('split.js', renderer => {
182+
const context = { url: '/test' }
183+
renderer.renderToString(context, (err, res) => {
184+
expect(err).toBeNull()
185+
expect(res).toBe('<div server-rendered="true">/test<div>async</div></div>')
186+
done()
187+
})
188+
}, { asBundle: true })
189+
})
190+
191+
it('renderToStream (bundle format with code split)', done => {
192+
createRenderer('split.js', renderer => {
193+
const context = { url: '/test' }
194+
const stream = renderer.renderToStream(context)
195+
let res = ''
196+
stream.on('data', chunk => {
197+
res += chunk.toString()
198+
})
199+
stream.on('end', () => {
200+
expect(res).toBe('<div server-rendered="true">/test<div>async</div></div>')
201+
done()
202+
})
203+
}, { asBundle: true })
204+
})
205+
206+
it('renderToString catch error (bundle format with source map)', done => {
207+
createRenderer('error.js', renderer => {
208+
renderer.renderToString(err => {
209+
expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')
210+
expect(err.message).toBe('foo')
211+
done()
212+
})
213+
}, { asBundle: true })
214+
})
215+
216+
it('renderToString catch error (bundle format with source map)', done => {
217+
createRenderer('error.js', renderer => {
218+
const stream = renderer.renderToStream()
219+
stream.on('error', err => {
220+
expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')
221+
expect(err.message).toBe('foo')
222+
done()
223+
})
224+
}, { asBundle: true })
225+
})
165226
})

Diff for: yarn.lock

+10-2
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,13 @@ [email protected], async@^1.4.0:
256256
version "1.5.2"
257257
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
258258

259-
[email protected], async@^2.0.0:
259+
260260
version "2.0.1"
261261
resolved "https://registry.yarnpkg.com/async/-/async-2.0.1.tgz#b709cc0280a9c36f09f4536be823c838a9049e25"
262262
dependencies:
263263
lodash "^4.8.0"
264264

265-
async@^2.1.2:
265+
async@^2.0.0, async@^2.1.2:
266266
version "2.1.4"
267267
resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4"
268268
dependencies:
@@ -459,6 +459,10 @@ babel-plugin-syntax-class-properties@^6.8.0:
459459
version "6.13.0"
460460
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
461461

462+
babel-plugin-syntax-dynamic-import@^6.18.0:
463+
version "6.18.0"
464+
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
465+
462466
babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.8.0:
463467
version "6.18.0"
464468
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
@@ -4903,6 +4907,10 @@ void-elements@^2.0.0:
49034907
version "2.0.1"
49044908
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
49054909

4910+
vue-ssr-webpack-plugin@^1.0.0:
4911+
version "1.0.0"
4912+
resolved "https://registry.yarnpkg.com/vue-ssr-webpack-plugin/-/vue-ssr-webpack-plugin-1.0.0.tgz#00b35a6b7d23689c65c1af838ef416b0a772b8f5"
4913+
49064914
watchpack@^1.2.0:
49074915
version "1.2.0"
49084916
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.2.0.tgz#15d4620f1e7471f13fcb551d5c030d2c3eb42dbb"

0 commit comments

Comments
 (0)