perf: also hoist all-static children array

This commit is contained in:
Evan You
2021-07-08 16:12:04 -04:00
parent 8bc50cb995
commit b7ea7c1485
7 changed files with 275 additions and 230 deletions

View File

@@ -286,6 +286,7 @@ export interface VNodeCall extends Node {
| TemplateTextChildNode // single text child
| SlotsExpression // component slots
| ForRenderListExpression // v-for fragment call
| SimpleExpressionNode // hoisted
| undefined
patchFlag: string | undefined
dynamicProps: string | SimpleExpressionNode | undefined
@@ -338,7 +339,7 @@ export interface Property extends Node {
export interface ArrayExpression extends Node {
type: NodeTypes.JS_ARRAY_EXPRESSION
elements: Array<string | JSChildNode>
elements: Array<string | Node>
}
export interface FunctionExpression extends Node {

View File

@@ -840,7 +840,7 @@ function genObjectExpression(node: ObjectExpression, context: CodegenContext) {
}
function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
genNodeListAsArray(node.elements, context)
genNodeListAsArray(node.elements as CodegenNode[], context)
}
function genFunctionExpression(

View File

@@ -16,7 +16,8 @@ import {
createCacheExpression,
TemplateLiteral,
createVNodeCall,
ConstantTypes
ConstantTypes,
ArrayExpression
} from './ast'
import {
isString,
@@ -113,7 +114,7 @@ export interface TransformContext
onNodeRemoved(): void
addIdentifiers(exp: ExpressionNode | string): void
removeIdentifiers(exp: ExpressionNode | string): void
hoist(exp: string | JSChildNode): SimpleExpressionNode
hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
constantCache: Map<TemplateChildNode, ConstantTypes>

View File

@@ -11,10 +11,11 @@ import {
VNodeCall,
ParentNode,
JSChildNode,
CallExpression
CallExpression,
createArrayExpression
} from '../ast'
import { TransformContext } from '../transform'
import { PatchFlags, isString, isSymbol } from '@vue/shared'
import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
import { getVNodeBlockHelper, getVNodeHelper, isSlotOutlet } from '../utils'
import {
OPEN_BLOCK,
@@ -51,7 +52,6 @@ function walk(
context: TransformContext,
doNotHoistNode: boolean = false
) {
let hasHoistedNode = false
// Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces
// static bindings with expressions. These expressions are guaranteed to be
// constant so they are still eligible for hoisting, but they are only
@@ -63,6 +63,9 @@ function walk(
let canStringify = true
const { children } = node
const originalCount = children.length
let hoistedCount = 0
for (let i = 0; i < children.length; i++) {
const child = children[i]
// only plain elements & text calls are eligible for hoisting.
@@ -81,7 +84,7 @@ function walk(
;(child.codegenNode as VNodeCall).patchFlag =
PatchFlags.HOISTED + (__DEV__ ? ` /* HOISTED */` : ``)
child.codegenNode = context.hoist(child.codegenNode!)
hasHoistedNode = true
hoistedCount++
continue
}
} else {
@@ -115,7 +118,7 @@ function walk(
}
if (contentType >= ConstantTypes.CAN_HOIST) {
child.codegenNode = context.hoist(child.codegenNode)
hasHoistedNode = true
hoistedCount++
}
}
}
@@ -145,9 +148,24 @@ function walk(
}
}
if (canStringify && hasHoistedNode && context.transformHoist) {
if (canStringify && hoistedCount && context.transformHoist) {
context.transformHoist(children, context, node)
}
// all children were hoisted - the entire children array is hoistable.
if (
hoistedCount &&
hoistedCount === originalCount &&
node.type === NodeTypes.ELEMENT &&
node.tagType === ElementTypes.ELEMENT &&
node.codegenNode &&
node.codegenNode.type === NodeTypes.VNODE_CALL &&
isArray(node.codegenNode.children)
) {
node.codegenNode.children = context.hoist(
createArrayExpression(node.codegenNode.children)
)
}
}
export function getConstantType(