Skip to content

perf: improve VNode creation performance with compiler hints #3334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: comments
  • Loading branch information
HcySunYang committed May 28, 2021
commit daa3598a9014023206d097904cb3950f59ec7069
4 changes: 2 additions & 2 deletions packages/compiler-core/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
push(PURE_ANNOTATION)
}
let callHelper: symbol = isBlock ? CREATE_BLOCK : CREATE_VNODE
if (!context.ssr) {
if (!context.forSSR) {
callHelper = isBlock
? isComponent
? CREATE_COMPONENT_BLOCK
Expand All @@ -793,7 +793,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
children,
patchFlag,
dynamicProps,
context.ssr ? null : shapeFlag
context.forSSR ? null : shapeFlag
]),
context
)
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler-core/src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,15 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
if (!codegenNode.isBlock) {
codegenNode.isBlock = true
removeHelper(
context.ssr
context.forSSR
? CREATE_VNODE
: codegenNode.isComponent
? CREATE_COMPONENT_VNODE
: CREATE_ELEMENT_VNODE
)
helper(OPEN_BLOCK)
helper(
context.ssr
context.forSSR
? CREATE_BLOCK
: codegenNode.isComponent
? CREATE_COMPONENT_BLOCK
Expand Down
13 changes: 7 additions & 6 deletions packages/compiler-core/src/transforms/hoistStatic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export function getConstantType(
)
codegenNode.isBlock = false
context.helper(
context.ssr
context.forSSR
? CREATE_VNODE
: codegenNode.isComponent
? CREATE_COMPONENT_VNODE
Expand Down Expand Up @@ -288,7 +288,7 @@ export function getConstantType(
}
}

const allowHoistedHelperSet = new Set<string | symbol>([
const allowHoistedHelperSet = new Set([
NORMALIZE_CLASS,
NORMALIZE_STYLE,
NORMALIZE_PROPS,
Expand All @@ -303,13 +303,14 @@ function getConstantTypeOfHelperCall(
): ConstantTypes {
if (
value.type === NodeTypes.JS_CALL_EXPRESSION &&
!isString(value.callee) &&
allowHoistedHelperSet.has(value.callee)
) {
const arg = value.arguments[0] as JSChildNode
if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
return getConstantType(arg, context)
} else if (arg.type === NodeTypes.JS_CALL_EXPRESSION) {
// in the case of nested calls, e.g. `normalizeProps(guardReactiveProps(exp))`
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`
return getConstantTypeOfHelperCall(arg, context)
}
}
Expand All @@ -334,9 +335,9 @@ function getGeneratedPropsConstantType(
returnType = keyType
}
if (value.type !== NodeTypes.SIMPLE_EXPRESSION) {
// some function calls can be hoisted,
// such as the `normalizeClass` call generated by the compiler for pre-normalize class,
// in this case we need to respect the ConstanType of the function's argments
// some helper calls can be hoisted,
// such as the `normalizeProps` generated by the compiler for pre-normalize class,
// in this case we need to respect the ConstanType of the helper's argments
if (value.type === NodeTypes.JS_CALL_EXPRESSION) {
return getConstantTypeOfHelperCall(value, context)
}
Expand Down
8 changes: 5 additions & 3 deletions packages/compiler-core/src/transforms/transformElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ export const transformElement: NodeTransform = (node, context) => {
shapeFlag |= ShapeFlags.TEXT_CHILDREN
} else {
vnodeChildren = node.children
// KeepAlive is a component, but no slot is built for it at compile time
vnodeTag !== KEEP_ALIVE && (shapeFlag |= ShapeFlags.ARRAY_CHILDREN)
}
} else {
Expand Down Expand Up @@ -446,6 +447,7 @@ export function buildProps(
dynamicPropNames.push(name)
}

// treat the dynamic binding class and style of the component as dynamic props
if (
isComponent &&
(name === 'class' || name === 'style') &&
Expand Down Expand Up @@ -690,7 +692,7 @@ export function buildProps(
patchFlag |= PatchFlags.NEED_PATCH
}

// pre-normalize props, SSR skip for now
// pre-normalize props, SSR is skipped for now
if (!context.forSSR && propsExpression) {
switch (propsExpression.type) {
case NodeTypes.JS_OBJECT_EXPRESSION:
Expand Down Expand Up @@ -786,8 +788,8 @@ export function buildProps(
}
}

// normalization is only needed when the dynamic binding key is before the binding of class and style
// i.e. <p :[dynamic]="val" :class="cls" :style="stl" />
// normalization is only needed when the dynamic binding key is before the class and style
// e.g. <p :[dynamic]="val" :class="cls" :style="stl" />
function doNormalize(
context: TransformContext,
properties: Property[],
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ export function injectProp(
createObjectExpression([prop]),
props
])
// in the case of `normalizeProps(guardReactiveProps(props))`,
// will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
// `guardReactiveProps` will no longer be needed
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,
// it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
// the `guardReactiveProps` will no longer be needed
if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) {
parentCall = callPath[callPath.length - 2]
}
Expand Down
4 changes: 1 addition & 3 deletions packages/runtime-core/src/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,9 +589,7 @@ function _createVNode(
// class & style normalization.
if (props) {
// for reactive or proxy objects, we need to clone it to enable mutation.
if (isProxy(props) || InternalObjectKey in props) {
props = extend({}, props)
}
props = guardReactiveProps(props)!
let { class: klass, style } = props
if (klass && !isString(klass)) {
props.class = normalizeClass(klass)
Expand Down