Evan You před 9 roky
rodič
revize
ac0e1687f3

+ 24 - 19
src/server/optimizing-compiler/codegen.js

@@ -54,7 +54,9 @@ function genSSRElement (el: ASTElement, state: CodegenState): string {
   } else if (el.if && !el.ifProcessed) {
     return genIf(el, state, genSSRElement)
   } else if (el.tag === 'template' && !el.slotTarget) {
-    return genSSRChildren(el, state) || 'void 0'
+    return el.ssrOptimizability === optimizability.FULL
+      ? genChildrenAsStringNode(el, state)
+      : genSSRChildren(el, state) || 'void 0'
   }
 
   switch (el.ssrOptimizability) {
@@ -79,7 +81,7 @@ function genSSRElement (el: ASTElement, state: CodegenState): string {
 function genNormalElement (el, state, stringifyChildren) {
   const data = el.plain ? undefined : genData(el, state)
   const children = stringifyChildren
-    ? genStringChildren(el, state)
+    ? `[${genChildrenAsStringNode(el, state)}]`
     : genSSRChildren(el, state, true)
   return `_c('${el.tag}'${
     data ? `,${data}` : ''
@@ -98,9 +100,9 @@ function genSSRNode (el, state) {
     : genText(el, state)
 }
 
-function genStringChildren (el, state) {
+function genChildrenAsStringNode (el, state) {
   return el.children.length
-    ? `[_ssrNode(${flattenSegments(childrenToSegments(el, state))})]`
+    ? `_ssrNode(${flattenSegments(childrenToSegments(el, state))})`
     : ''
 }
 
@@ -200,24 +202,27 @@ function childrenToSegments (el, state): Array<StringSegment> {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: binding }]
   }
+  return el.children
+    ? nodesToSegments(el.children, state)
+    : []
+}
 
-  const children = el.children
-  if (children) {
-    const segments = []
-    for (let i = 0; i < children.length; i++) {
-      const c = children[i]
-      if (c.type === 1) {
-        segments.push.apply(segments, elementToSegments(c, state))
-      } else if (c.type === 2) {
-        segments.push({ type: INTERPOLATION, value: c.expression })
-      } else if (c.type === 3) {
-        segments.push({ type: RAW, value: c.text })
-      }
+function nodesToSegments (
+  children: Array<ASTNode>,
+  state: CodegenState
+): Array<StringSegment> {
+  const segments = []
+  for (let i = 0; i < children.length; i++) {
+    const c = children[i]
+    if (c.type === 1) {
+      segments.push.apply(segments, elementToSegments(c, state))
+    } else if (c.type === 2) {
+      segments.push({ type: INTERPOLATION, value: c.expression })
+    } else if (c.type === 3) {
+      segments.push({ type: RAW, value: c.text })
     }
-    return segments
-  } else {
-    return []
   }
+  return segments
 }
 
 function flattenSegments (segments: Array<StringSegment>): string {

+ 37 - 0
src/server/optimizing-compiler/optimizer.js

@@ -64,12 +64,49 @@ function walk (node: ASTNode, isRoot?: boolean) {
       node.attrsMap['v-text']
     ) {
       node.ssrOptimizability = optimizability.FULL
+    } else {
+      node.children = optimizeSiblings(node)
     }
   } else {
     node.ssrOptimizability = optimizability.FULL
   }
 }
 
+function optimizeSiblings (el) {
+  const children = el.children
+  const optimizedChildren = []
+
+  let currentOptimizableGroup = []
+  const pushGroup = () => {
+    if (currentOptimizableGroup.length) {
+      optimizedChildren.push({
+        type: 1,
+        parent: el,
+        tag: 'template',
+        attrsList: [],
+        attrsMap: {},
+        children: currentOptimizableGroup,
+        ssrOptimizability: optimizability.FULL
+      })
+    }
+    currentOptimizableGroup = []
+  }
+
+  for (let i = 0; i < children.length; i++) {
+    const c = children[i]
+    if (c.ssrOptimizability === optimizability.FULL) {
+      currentOptimizableGroup.push(c)
+    } else {
+      // wrap fully-optimizable adjacent siblings inside a template tag
+      // so that they can be optimized into a single ssrNode by codegen
+      pushGroup()
+      optimizedChildren.push(c)
+    }
+  }
+  pushGroup()
+  return optimizedChildren
+}
+
 function isUnOptimizableTree (node: ASTNode): boolean {
   if (node.type === 2 || node.type === 3) { // text or expression
     return false