diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index b3a6b31c6d4..a783502fc77 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -449,7 +449,7 @@ function createSuspenseBoundary( return suspense } -function normalizeSuspenseChildren( +export function normalizeSuspenseChildren( vnode: VNode ): { content: VNode diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index d0b8444a8fd..9717174bbe3 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -114,6 +114,7 @@ import { setCurrentRenderingInstance } from './componentRenderUtils' import { isVNode, normalizeVNode } from './vnode' +import { normalizeSuspenseChildren } from './components/Suspense' // SSR utils are only exposed in cjs builds. const _ssrUtils = { @@ -122,7 +123,8 @@ const _ssrUtils = { renderComponentRoot, setCurrentRenderingInstance, isVNode, - normalizeVNode + normalizeVNode, + normalizeSuspenseChildren } export const ssrUtils = (__NODE_JS__ ? _ssrUtils : null) as typeof _ssrUtils diff --git a/packages/server-renderer/src/renderToString.ts b/packages/server-renderer/src/renderToString.ts index fc8dd18f60a..8051c204b4f 100644 --- a/packages/server-renderer/src/renderToString.ts +++ b/packages/server-renderer/src/renderToString.ts @@ -36,7 +36,8 @@ const { setCurrentRenderingInstance, setupComponent, renderComponentRoot, - normalizeVNode + normalizeVNode, + normalizeSuspenseChildren } = ssrUtils // Each component has a buffer array. @@ -224,27 +225,6 @@ function ssrCompile( return (compileCache[template] = Function('require', code)(require)) } -function normalizeSuspenseChildren( - vnode: VNode -): { - content: VNode - fallback: VNode -} { - const { shapeFlag, children } = vnode - if (shapeFlag & ShapeFlags.SLOTS_CHILDREN) { - const { default: d, fallback } = children as Slots - return { - content: normalizeVNode(isFunction(d) ? d() : d), - fallback: normalizeVNode(isFunction(fallback) ? fallback() : fallback) - } - } else { - return { - content: normalizeVNode(children as any), - fallback: normalizeVNode(null) - } - } -} - function renderVNode( push: PushFn, vnode: VNode, @@ -269,21 +249,7 @@ function renderVNode( } else if (shapeFlag & ShapeFlags.PORTAL) { renderPortal(vnode, parentComponent) } else if (shapeFlag & ShapeFlags.SUSPENSE) { - const { content, fallback } = normalizeSuspenseChildren(vnode) - - push( - (async () => { - try { - const suspenseBuffer = createBuffer() - renderVNode(suspenseBuffer.push, content, parentComponent) - return await Promise.all(suspenseBuffer.buffer) - } catch { - const fallbackBuffer = createBuffer() - renderVNode(fallbackBuffer.push, fallback, parentComponent) - return await Promise.all(fallbackBuffer.buffer) - } - })() - ) + push(renderSuspense(vnode, parentComponent)) } else { console.warn( '[@vue/server-renderer] Invalid VNode type:', @@ -400,3 +366,19 @@ async function resolvePortals(context: SSRContext) { } } } + +async function renderSuspense( + vnode: VNode, + parentComponent: ComponentInternalInstance +): Promise { + const { content, fallback } = normalizeSuspenseChildren(vnode) + try { + const { push, getBuffer } = createBuffer() + renderVNode(push, content, parentComponent) + return await getBuffer() + } catch { + const { push, getBuffer } = createBuffer() + renderVNode(push, fallback, parentComponent) + return getBuffer() + } +}