fix(ssr): support dynamic components that resolve to element or vnode
fix #1508
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { registerRuntimeHelpers } from '@vue/compiler-dom'
|
||||
|
||||
export const SSR_INTERPOLATE = Symbol(`ssrInterpolate`)
|
||||
export const SSR_RENDER_VNODE = Symbol(`ssrRenderVNode`)
|
||||
export const SSR_RENDER_COMPONENT = Symbol(`ssrRenderComponent`)
|
||||
export const SSR_RENDER_SLOT = Symbol(`ssrRenderSlot`)
|
||||
export const SSR_RENDER_CLASS = Symbol(`ssrRenderClass`)
|
||||
@@ -18,6 +19,7 @@ export const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`)
|
||||
|
||||
export const ssrHelpers = {
|
||||
[SSR_INTERPOLATE]: `ssrInterpolate`,
|
||||
[SSR_RENDER_VNODE]: `ssrRenderVNode`,
|
||||
[SSR_RENDER_COMPONENT]: `ssrRenderComponent`,
|
||||
[SSR_RENDER_SLOT]: `ssrRenderSlot`,
|
||||
[SSR_RENDER_CLASS]: `ssrRenderClass`,
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
buildSlots,
|
||||
FunctionExpression,
|
||||
TemplateChildNode,
|
||||
TELEPORT,
|
||||
createIfStatement,
|
||||
createSimpleExpression,
|
||||
getBaseTransformPreset,
|
||||
@@ -31,9 +30,12 @@ import {
|
||||
ExpressionNode,
|
||||
TemplateNode,
|
||||
SUSPENSE,
|
||||
TRANSITION_GROUP
|
||||
TELEPORT,
|
||||
TRANSITION_GROUP,
|
||||
CREATE_VNODE,
|
||||
CallExpression
|
||||
} from '@vue/compiler-dom'
|
||||
import { SSR_RENDER_COMPONENT } from '../runtimeHelpers'
|
||||
import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers'
|
||||
import {
|
||||
SSRTransformContext,
|
||||
processChildren,
|
||||
@@ -58,7 +60,10 @@ interface WIPSlotEntry {
|
||||
vnodeBranch: ReturnStatement
|
||||
}
|
||||
|
||||
const componentTypeMap = new WeakMap<ComponentNode, symbol>()
|
||||
const componentTypeMap = new WeakMap<
|
||||
ComponentNode,
|
||||
string | symbol | CallExpression
|
||||
>()
|
||||
|
||||
// ssr component transform is done in two phases:
|
||||
// In phase 1. we use `buildSlot` to analyze the children of the component into
|
||||
@@ -75,8 +80,9 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
|
||||
}
|
||||
|
||||
const component = resolveComponentType(node, context, true /* ssr */)
|
||||
componentTypeMap.set(node, component)
|
||||
|
||||
if (isSymbol(component)) {
|
||||
componentTypeMap.set(node, component)
|
||||
if (component === SUSPENSE) {
|
||||
return ssrTransformSuspense(node, context)
|
||||
}
|
||||
@@ -134,10 +140,28 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
|
||||
? buildSlots(node, context, buildSSRSlotFn).slots
|
||||
: `null`
|
||||
|
||||
node.ssrCodegenNode = createCallExpression(
|
||||
context.helper(SSR_RENDER_COMPONENT),
|
||||
[component, props, slots, `_parent`]
|
||||
)
|
||||
if (typeof component !== 'string') {
|
||||
// dynamic component that resolved to a `resolveDynamicComponent` call
|
||||
// expression - since the reoslved result may be a plain element (string)
|
||||
// or a VNode, handle it with `renderVNode`.
|
||||
node.ssrCodegenNode = createCallExpression(
|
||||
context.helper(SSR_RENDER_VNODE),
|
||||
[
|
||||
`_push`,
|
||||
createCallExpression(context.helper(CREATE_VNODE), [
|
||||
component,
|
||||
props,
|
||||
slots
|
||||
]),
|
||||
`_parent`
|
||||
]
|
||||
)
|
||||
} else {
|
||||
node.ssrCodegenNode = createCallExpression(
|
||||
context.helper(SSR_RENDER_COMPONENT),
|
||||
[component, props, slots, `_parent`]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,9 +169,9 @@ export function ssrProcessComponent(
|
||||
node: ComponentNode,
|
||||
context: SSRTransformContext
|
||||
) {
|
||||
const component = componentTypeMap.get(node)!
|
||||
if (!node.ssrCodegenNode) {
|
||||
// this is a built-in component that fell-through.
|
||||
const component = componentTypeMap.get(node)!
|
||||
if (component === TELEPORT) {
|
||||
return ssrProcessTeleport(node, context)
|
||||
} else if (component === SUSPENSE) {
|
||||
@@ -176,7 +200,16 @@ export function ssrProcessComponent(
|
||||
vnodeBranch
|
||||
)
|
||||
}
|
||||
context.pushStatement(createCallExpression(`_push`, [node.ssrCodegenNode]))
|
||||
if (typeof component === 'string') {
|
||||
// static component
|
||||
context.pushStatement(
|
||||
createCallExpression(`_push`, [node.ssrCodegenNode])
|
||||
)
|
||||
} else {
|
||||
// dynamic component (`resolveDynamicComponent` call)
|
||||
// the codegen node is a `renderVNode` call
|
||||
context.pushStatement(node.ssrCodegenNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user