@@ -30,17 +30,20 @@ import {
30
30
traverseNode ,
31
31
ExpressionNode ,
32
32
TemplateNode ,
33
- findProp ,
34
- JSChildNode
33
+ SUSPENSE
35
34
} from '@vue/compiler-dom'
36
- import { SSR_RENDER_COMPONENT , SSR_RENDER_PORTAL } from '../runtimeHelpers'
35
+ import { SSR_RENDER_COMPONENT } from '../runtimeHelpers'
37
36
import {
38
37
SSRTransformContext ,
39
38
processChildren ,
40
39
processChildrenAsStatement
41
40
} from '../ssrCodegenTransform'
41
+ import { ssrProcessPortal } from './ssrTransformPortal'
42
+ import {
43
+ ssrProcessSuspense ,
44
+ ssrTransformSuspense
45
+ } from './ssrTransformSuspense'
42
46
import { isSymbol , isObject , isArray } from '@vue/shared'
43
- import { createSSRCompilerError , SSRErrorCodes } from '../errors'
44
47
45
48
// We need to construct the slot functions in the 1st pass to ensure proper
46
49
// scope tracking, but the children of each slot cannot be processed until
@@ -56,6 +59,12 @@ interface WIPSlotEntry {
56
59
57
60
const componentTypeMap = new WeakMap < ComponentNode , symbol > ( )
58
61
62
+ // ssr component transform is done in two phases:
63
+ // In phase 1. we use `buildSlot` to analyze the children of the component into
64
+ // WIP slot functions (it must be done in phase 1 because `buildSlot` relies on
65
+ // the core transform context).
66
+ // In phase 2. we convert the WIP slots from phase 1 into ssr-specific codegen
67
+ // nodes.
59
68
export const ssrTransformComponent : NodeTransform = ( node , context ) => {
60
69
if (
61
70
node . type !== NodeTypes . ELEMENT ||
@@ -67,6 +76,9 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
67
76
const component = resolveComponentType ( node , context , true /* ssr */ )
68
77
if ( isSymbol ( component ) ) {
69
78
componentTypeMap . set ( node , component )
79
+ if ( component === SUSPENSE ) {
80
+ return ssrTransformSuspense ( node , context )
81
+ }
70
82
return // built-in component: fallthrough
71
83
}
72
84
@@ -132,12 +144,15 @@ export function ssrProcessComponent(
132
144
) {
133
145
if ( ! node . ssrCodegenNode ) {
134
146
// this is a built-in component that fell-through.
135
- // just render its children.
136
147
const component = componentTypeMap . get ( node ) !
137
148
if ( component === PORTAL ) {
138
149
return ssrProcessPortal ( node , context )
150
+ } else if ( component === SUSPENSE ) {
151
+ return ssrProcessSuspense ( node , context )
152
+ } else {
153
+ // real fall-through (e.g. KeepAlive): just render its children.
154
+ processChildren ( node . children , context )
139
155
}
140
- processChildren ( node . children , context )
141
156
} else {
142
157
// finish up slot function expressions from the 1st pass.
143
158
const wipEntries = wipMap . get ( node ) || [ ]
@@ -161,47 +176,6 @@ export function ssrProcessComponent(
161
176
}
162
177
}
163
178
164
- function ssrProcessPortal ( node : ComponentNode , context : SSRTransformContext ) {
165
- const targetProp = findProp ( node , 'target' )
166
- if ( ! targetProp ) {
167
- context . onError (
168
- createSSRCompilerError ( SSRErrorCodes . X_SSR_NO_PORTAL_TARGET , node . loc )
169
- )
170
- return
171
- }
172
-
173
- let target : JSChildNode
174
- if ( targetProp . type === NodeTypes . ATTRIBUTE && targetProp . value ) {
175
- target = createSimpleExpression ( targetProp . value . content , true )
176
- } else if ( targetProp . type === NodeTypes . DIRECTIVE && targetProp . exp ) {
177
- target = targetProp . exp
178
- } else {
179
- context . onError (
180
- createSSRCompilerError (
181
- SSRErrorCodes . X_SSR_NO_PORTAL_TARGET ,
182
- targetProp . loc
183
- )
184
- )
185
- return
186
- }
187
-
188
- const contentRenderFn = createFunctionExpression (
189
- [ `_push` ] ,
190
- undefined , // Body is added later
191
- true , // newline
192
- false , // isSlot
193
- node . loc
194
- )
195
- contentRenderFn . body = processChildrenAsStatement ( node . children , context )
196
- context . pushStatement (
197
- createCallExpression ( context . helper ( SSR_RENDER_PORTAL ) , [
198
- contentRenderFn ,
199
- target ,
200
- `_parent`
201
- ] )
202
- )
203
- }
204
-
205
179
export const rawOptionsMap = new WeakMap < RootNode , CompilerOptions > ( )
206
180
207
181
const [ baseNodeTransforms , baseDirectiveTransforms ] = getBaseTransformPreset (
0 commit comments