Skip to content

Commit 4b4fb1e

Browse files
authored
perf: use createElementVNode (#2)
1 parent e1eca4d commit 4b4fb1e

File tree

4 files changed

+116
-77
lines changed

4 files changed

+116
-77
lines changed

packages/babel-plugin-jsx/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export default declare<VueJSXPluginOptions, BabelCore.PluginObj<State>>(
6161
if (hasJSX(path)) {
6262
const importNames = [
6363
'createVNode',
64+
'createElementVNode',
6465
'Fragment',
6566
'resolveComponent',
6667
'withDirectives',
@@ -73,6 +74,10 @@ export default declare<VueJSXPluginOptions, BabelCore.PluginObj<State>>(
7374
'vModelDynamic',
7475
'resolveDirective',
7576
'mergeProps',
77+
'normalizeProps',
78+
'normalizeClass',
79+
'normalizeStyle',
80+
'guardReactiveProps',
7681
'createTextVNode',
7782
'isVNode',
7883
];
@@ -179,6 +184,7 @@ export default declare<VueJSXPluginOptions, BabelCore.PluginObj<State>>(
179184

180185
if (pragma) {
181186
state.set('createVNode', () => t.identifier(pragma));
187+
state.set('createElementVNode', () => t.identifier(pragma));
182188
}
183189

184190
if (file.ast.comments) {

packages/babel-plugin-jsx/src/transform-vue-jsx.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,19 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
310310
);
311311
} else {
312312
// single no need for a mergeProps call
313-
propsExpression = mergeArgs[0];
313+
if (isComponent) {
314+
// createVNode already normalizes props
315+
propsExpression = mergeArgs[0];
316+
} else {
317+
propsExpression = t.callExpression(
318+
createIdentifier(state, 'normalizeProps'),
319+
[
320+
t.callExpression(createIdentifier(state, 'guardReactiveProps'), [
321+
mergeArgs[0],
322+
]),
323+
]
324+
);
325+
}
314326
}
315327
} else if (properties.length) {
316328
// single no need for spread
@@ -320,6 +332,27 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
320332
propsExpression = t.objectExpression(
321333
dedupeProperties(properties, mergeProps)
322334
);
335+
for (let i = 0; i < propsExpression.properties.length; i++) {
336+
const property = propsExpression.properties[i];
337+
if (
338+
!t.isObjectProperty(property) ||
339+
!t.isStringLiteral(property.key) ||
340+
!t.isExpression(property.value) ||
341+
isConstant(property.value)
342+
)
343+
continue;
344+
if (property.key.value === 'class') {
345+
property.value = t.callExpression(
346+
createIdentifier(state, 'normalizeClass'),
347+
[property.value]
348+
);
349+
} else if (property.key.value === 'style') {
350+
property.value = t.callExpression(
351+
createIdentifier(state, 'normalizeStyle'),
352+
[property.value]
353+
);
354+
}
355+
}
323356
}
324357
}
325358

@@ -553,7 +586,7 @@ const transformJSXElement = (
553586
}
554587

555588
const createVNode = t.callExpression(
556-
createIdentifier(state, 'createVNode'),
589+
createIdentifier(state, isComponent ? 'createVNode' : 'createElementVNode'),
557590
[
558591
tag,
559592
props,

packages/babel-plugin-jsx/test/__snapshots__/resolve-type.test.tsx.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`resolve type > runtime props > basic 1`] = `
4-
"import { createVNode as _createVNode } from "vue";
4+
"import { createElementVNode as _createElementVNode } from "vue";
55
interface Props {
66
foo?: string;
77
}
8-
const App = defineComponent((props: Props) => _createVNode("div", null, null), {
8+
const App = defineComponent((props: Props) => _createElementVNode("div", null, null), {
99
props: {
1010
foo: {
1111
type: String,

0 commit comments

Comments
 (0)