|
1 | 1 | /* @flow */
|
2 | 2 |
|
| 3 | +import { |
| 4 | + isDef, |
| 5 | + isUndef, |
| 6 | + isTrue |
| 7 | +} from 'shared/util' |
| 8 | + |
3 | 9 | import { escape } from 'web/server/util'
|
4 | 10 | import { SSR_ATTR } from 'shared/constants'
|
5 | 11 | import { RenderContext } from './render-context'
|
6 | 12 | import { ssrCompileToFunctions } from 'web/server/compiler'
|
7 | 13 | import { installSSRHelpers } from './optimizing-compiler/runtime-helpers'
|
8 |
| -import { createComponentInstanceForVnode } from 'core/vdom/create-component' |
9 | 14 |
|
10 |
| -import { isDef, isUndef, isTrue } from 'shared/util' |
| 15 | +import { |
| 16 | + createComponent, |
| 17 | + createComponentInstanceForVnode |
| 18 | +} from 'core/vdom/create-component' |
11 | 19 |
|
12 | 20 | let warned = Object.create(null)
|
13 | 21 | const warnOnce = msg => {
|
@@ -39,20 +47,20 @@ function renderNode (node, isRoot, context) {
|
39 | 47 | renderStringNode(node, context)
|
40 | 48 | } else if (isDef(node.componentOptions)) {
|
41 | 49 | renderComponent(node, isRoot, context)
|
42 |
| - } else { |
43 |
| - if (isDef(node.tag)) { |
44 |
| - renderElement(node, isRoot, context) |
45 |
| - } else if (isTrue(node.isComment)) { |
46 |
| - context.write( |
47 |
| - `<!--${node.text}-->`, |
48 |
| - context.next |
49 |
| - ) |
| 50 | + } else if (isDef(node.tag)) { |
| 51 | + renderElement(node, isRoot, context) |
| 52 | + } else if (isTrue(node.isComment)) { |
| 53 | + if (isDef(node.asyncFactory)) { |
| 54 | + // async component |
| 55 | + renderAsyncComponent(node, isRoot, context) |
50 | 56 | } else {
|
51 |
| - context.write( |
52 |
| - node.raw ? node.text : escape(String(node.text)), |
53 |
| - context.next |
54 |
| - ) |
| 57 | + context.write(`<!--${node.text}-->`, context.next) |
55 | 58 | }
|
| 59 | + } else { |
| 60 | + context.write( |
| 61 | + node.raw ? node.text : escape(String(node.text)), |
| 62 | + context.next |
| 63 | + ) |
56 | 64 | }
|
57 | 65 | }
|
58 | 66 |
|
@@ -160,6 +168,56 @@ function renderComponentInner (node, isRoot, context) {
|
160 | 168 | renderNode(childNode, isRoot, context)
|
161 | 169 | }
|
162 | 170 |
|
| 171 | +function renderAsyncComponent (node, isRoot, context) { |
| 172 | + const factory = node.asyncFactory |
| 173 | + |
| 174 | + const resolve = comp => { |
| 175 | + const { data, children, tag } = node.asyncMeta |
| 176 | + const nodeContext = node.asyncMeta.context |
| 177 | + const resolvedNode: any = createComponent( |
| 178 | + comp, |
| 179 | + data, |
| 180 | + nodeContext, |
| 181 | + children, |
| 182 | + tag |
| 183 | + ) |
| 184 | + if (resolvedNode) { |
| 185 | + renderComponent(resolvedNode, isRoot, context) |
| 186 | + } else { |
| 187 | + reject() |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + const reject = err => { |
| 192 | + console.error(`[vue-server-renderer] error when rendering async component:\n`) |
| 193 | + if (err) console.error(err.stack) |
| 194 | + context.write(`<!--${node.text}-->`, context.next) |
| 195 | + } |
| 196 | + |
| 197 | + if (factory.resolved) { |
| 198 | + resolve(factory.resolved) |
| 199 | + return |
| 200 | + } |
| 201 | + |
| 202 | + let res |
| 203 | + try { |
| 204 | + res = factory(resolve, reject) |
| 205 | + } catch (e) { |
| 206 | + reject(e) |
| 207 | + } |
| 208 | + if (res) { |
| 209 | + if (typeof res.then === 'function') { |
| 210 | + res.then(resolve, reject).catch(reject) |
| 211 | + } else { |
| 212 | + // new syntax in 2.3 |
| 213 | + const comp = res.component |
| 214 | + if (comp && typeof comp.then === 'function') { |
| 215 | + comp.then(resolve, reject).catch(reject) |
| 216 | + } |
| 217 | + } |
| 218 | + } |
| 219 | +} |
| 220 | + |
163 | 221 | function renderStringNode (el, context) {
|
164 | 222 | const { write, next } = context
|
165 | 223 | if (isUndef(el.children) || el.children.length === 0) {
|
|
0 commit comments