Skip to content

Commit d965bb6

Browse files
committed
feat: improve static content stringiciation
Now a single static vnode can contain stringified content for multiple consecutive nodes, which greatly improves the coverage of this optimization.
1 parent 59d50da commit d965bb6

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ function walk(
4343
resultCache: Map<TemplateChildNode, boolean>,
4444
doNotHoistNode: boolean = false
4545
) {
46+
let hasHoistedNode = false
4647
for (let i = 0; i < children.length; i++) {
4748
const child = children[i]
4849
// only plain elements & text calls are eligible for hoisting.
@@ -55,6 +56,7 @@ function walk(
5556
;(child.codegenNode as VNodeCall).patchFlag =
5657
PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
5758
child.codegenNode = context.hoist(child.codegenNode!)
59+
hasHoistedNode = true
5860
continue
5961
} else {
6062
// node may contain dynamic children, but its props may be eligible for
@@ -81,6 +83,7 @@ function walk(
8183
isStaticNode(child.content, resultCache)
8284
) {
8385
child.codegenNode = context.hoist(child.codegenNode)
86+
hasHoistedNode = true
8487
}
8588

8689
// walk further
@@ -98,7 +101,7 @@ function walk(
98101
}
99102
}
100103

101-
if (context.transformHoist) {
104+
if (hasHoistedNode && context.transformHoist) {
102105
context.transformHoist(children, context)
103106
}
104107
}

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

+23-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,29 @@ export const enum StringifyThresholds {
3535

3636
type StringiableNode = PlainElementNode | TextCallNode
3737

38-
// Turn eligible hoisted static trees into stringied static nodes, e.g.
39-
// const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
40-
// This is only performed in non-in-browser compilations.
38+
/**
39+
* Turn eligible hoisted static trees into stringied static nodes, e.g.
40+
*
41+
* ```js
42+
* const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
43+
* ```
44+
*
45+
* A single static vnode can contain stringified content for **multiple**
46+
* consecutive nodes (element and plain text), called a "chunk".
47+
* `@vue/runtime-dom` will create the content via innerHTML in a hidden
48+
* container element and insert all the nodes in place. The call must also
49+
* provide the number of nodes contained in the chunk so that during hydration
50+
* we can know how many nodes the static vnode should adopt.
51+
*
52+
* The optimization scans a children list that contains hoisted nodes, and
53+
* tries to find the largest chunk of consecutive hoisted nodes before running
54+
* into a non-hoisted node or the end of the list. A chunk is then converted
55+
* into a single static vnode and replaces the hoisted expression of the first
56+
* node in the chunk. Other nodes in the chunk are considered "merged" and
57+
* therefore removed from both the hoist list and the children array.
58+
*
59+
* This optimization is only performed in Node.js.
60+
*/
4161
export const stringifyStatic: HoistTransform = (children, context) => {
4262
let nc = 0 // current node count
4363
let ec = 0 // current element with binding count

0 commit comments

Comments
 (0)