]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat: improve static content stringiciation
authorEvan You <yyx990803@gmail.com>
Sun, 17 May 2020 01:30:16 +0000 (21:30 -0400)
committerEvan You <yyx990803@gmail.com>
Sun, 17 May 2020 01:30:16 +0000 (21:30 -0400)
Now a single static vnode can contain stringified content
for multiple consecutive nodes, which greatly improves the
coverage of this optimization.

packages/compiler-core/src/transforms/hoistStatic.ts
packages/compiler-dom/src/transforms/stringifyStatic.ts

index 59ba445ccbe6a6f42d3ac5e9e60cbdbd2fa267b2..38ea88aed87459e3be4ca6152703b7ce515b3435 100644 (file)
@@ -43,6 +43,7 @@ function walk(
   resultCache: Map<TemplateChildNode, boolean>,
   doNotHoistNode: boolean = false
 ) {
+  let hasHoistedNode = false
   for (let i = 0; i < children.length; i++) {
     const child = children[i]
     // only plain elements & text calls are eligible for hoisting.
@@ -55,6 +56,7 @@ function walk(
         ;(child.codegenNode as VNodeCall).patchFlag =
           PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
         child.codegenNode = context.hoist(child.codegenNode!)
+        hasHoistedNode = true
         continue
       } else {
         // node may contain dynamic children, but its props may be eligible for
@@ -81,6 +83,7 @@ function walk(
       isStaticNode(child.content, resultCache)
     ) {
       child.codegenNode = context.hoist(child.codegenNode)
+      hasHoistedNode = true
     }
 
     // walk further
@@ -98,7 +101,7 @@ function walk(
     }
   }
 
-  if (context.transformHoist) {
+  if (hasHoistedNode && context.transformHoist) {
     context.transformHoist(children, context)
   }
 }
index a48dabcbdd4535ec27a24c09962cae5405427ce5..a022d04091f1f59040509e1bc3ae4452f4a7bb07 100644 (file)
@@ -35,9 +35,29 @@ export const enum StringifyThresholds {
 
 type StringiableNode = PlainElementNode | TextCallNode
 
-// Turn eligible hoisted static trees into stringied static nodes, e.g.
-//   const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
-// This is only performed in non-in-browser compilations.
+/**
+ * Turn eligible hoisted static trees into stringied static nodes, e.g.
+ *
+ * ```js
+ * const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
+ * ```
+ *
+ * A single static vnode can contain stringified content for **multiple**
+ * consecutive nodes (element and plain text), called a "chunk".
+ * `@vue/runtime-dom` will create the content via innerHTML in a hidden
+ * container element and insert all the nodes in place. The call must also
+ * provide the number of nodes contained in the chunk so that during hydration
+ * we can know how many nodes the static vnode should adopt.
+ *
+ * The optimization scans a children list that contains hoisted nodes, and
+ * tries to find the largest chunk of consecutive hoisted nodes before running
+ * into a non-hoisted node or the end of the list. A chunk is then converted
+ * into a single static vnode and replaces the hoisted expression of the first
+ * node in the chunk. Other nodes in the chunk are considered "merged" and
+ * therefore removed from both the hoist list and the children array.
+ *
+ * This optimization is only performed in Node.js.
+ */
 export const stringifyStatic: HoistTransform = (children, context) => {
   let nc = 0 // current node count
   let ec = 0 // current element with binding count