]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(ssr): extract buffer resolving and resolvePortals (#771)
authorXin Du (Clark) <clark.duxin@gmail.com>
Mon, 24 Feb 2020 16:23:35 +0000 (16:23 +0000)
committerGitHub <noreply@github.com>
Mon, 24 Feb 2020 16:23:35 +0000 (17:23 +0100)
packages/server-renderer/src/renderToString.ts

index 2753c3455384c15e110fd89d3aa62d22947932db..0aac04cd14a38137d649f25806944bc141a3a726 100644 (file)
@@ -67,9 +67,11 @@ function createBuffer() {
   let hasAsync = false
   const buffer: SSRBuffer = []
   return {
-    buffer,
-    hasAsync() {
-      return hasAsync
+    getBuffer(): ResolvedSSRBuffer | Promise<ResolvedSSRBuffer> {
+      // If the current component's buffer contains any Promise from async children,
+      // then it must return a Promise too. Otherwise this is a component that
+      // contains only sync children so we can avoid the async book-keeping overhead.
+      return hasAsync ? Promise.all(buffer) : (buffer as ResolvedSSRBuffer)
     },
     push(item: SSRBufferItem) {
       const isStringItem = isString(item)
@@ -104,28 +106,19 @@ export async function renderToString(
   input: App | VNode,
   context: SSRContext = {}
 ): Promise<string> {
-  let buffer: ResolvedSSRBuffer
   if (isVNode(input)) {
     // raw vnode, wrap with app (for context)
     return renderToString(createApp({ render: () => input }), context)
-  } else {
-    // rendering an app
-    const vnode = createVNode(input._component, input._props)
-    vnode.appContext = input._context
-    // provide the ssr context to the tree
-    input.provide(ssrContextKey, context)
-    buffer = await renderComponentVNode(vnode)
   }
 
-  // resolve portals
-  if (context.__portalBuffers) {
-    context.portals = context.portals || {}
-    for (const key in context.__portalBuffers) {
-      // note: it's OK to await sequentially here because the Promises were
-      // created eagerly in parallel.
-      context.portals[key] = unrollBuffer(await context.__portalBuffers[key])
-    }
-  }
+  // rendering an app
+  const vnode = createVNode(input._component, input._props)
+  vnode.appContext = input._context
+  // provide the ssr context to the tree
+  input.provide(ssrContextKey, context)
+  const buffer = await renderComponentVNode(vnode)
+
+  await resolvePortals(context)
 
   return unrollBuffer(buffer)
 }
@@ -201,7 +194,7 @@ function renderComponentSubTree(
   instance: ComponentInternalInstance
 ): ResolvedSSRBuffer | Promise<ResolvedSSRBuffer> {
   const comp = instance.type as Component
-  const { buffer, push, hasAsync } = createBuffer()
+  const { getBuffer, push } = createBuffer()
   if (isFunction(comp)) {
     renderVNode(push, renderComponentRoot(instance), instance)
   } else {
@@ -225,10 +218,7 @@ function renderComponentSubTree(
       )
     }
   }
-  // If the current component's buffer contains any Promise from async children,
-  // then it must return a Promise too. Otherwise this is a component that
-  // contains only sync children so we can avoid the async book-keeping overhead.
-  return hasAsync() ? Promise.all(buffer) : (buffer as ResolvedSSRBuffer)
+  return getBuffer()
 }
 
 function renderVNode(
@@ -349,7 +339,7 @@ function renderPortal(
     return []
   }
 
-  const { buffer, push, hasAsync } = createBuffer()
+  const { getBuffer, push } = createBuffer()
   renderVNodeChildren(
     push,
     vnode.children as VNodeArrayChildren,
@@ -360,7 +350,17 @@ function renderPortal(
   ] as SSRContext
   const portalBuffers =
     context.__portalBuffers || (context.__portalBuffers = {})
-  portalBuffers[target] = hasAsync()
-    ? Promise.all(buffer)
-    : (buffer as ResolvedSSRBuffer)
+
+  portalBuffers[target] = getBuffer()
+}
+
+async function resolvePortals(context: SSRContext) {
+  if (context.__portalBuffers) {
+    context.portals = context.portals || {}
+    for (const key in context.__portalBuffers) {
+      // note: it's OK to await sequentially here because the Promises were
+      // created eagerly in parallel.
+      context.portals[key] = unrollBuffer(await context.__portalBuffers[key])
+    }
+  }
 }