Skip to content

Commit c494282

Browse files
committed
refactor: optimize bundle size
1 parent 6608c78 commit c494282

22 files changed

+145
-160
lines changed

packages/babel/src/index.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ export type Options = {
1414
filename: string
1515
importSet: Set<string>
1616
delegateEventSet: Set<string>
17-
preambleMap: Map<string, string>
18-
preambleIndex: number
17+
templates: string[]
1918
file: BabelFile
2019
roots: {
2120
node: JSXElement | JSXFragment
@@ -43,8 +42,7 @@ export default (): {
4342
enter: (path, state) => {
4443
state.importSet = new Set<string>()
4544
state.delegateEventSet = new Set<string>()
46-
state.preambleMap = new Map<string, string>()
47-
state.preambleIndex = 0
45+
state.templates = []
4846
state.roots = []
4947
const collectRoot: VisitNodeFunction<
5048
Node,
@@ -78,20 +76,24 @@ export default (): {
7876
})
7977
},
8078
exit: (path, state) => {
81-
const { delegateEventSet, importSet, preambleMap } = state
79+
const { delegateEventSet, importSet, templates } = state
8280

8381
const statements: string[] = []
8482
if (delegateEventSet.size) {
8583
statements.unshift(
86-
`_delegateEvents(${Array.from(delegateEventSet).join(', ')});`,
84+
`_delegateEvents("${Array.from(delegateEventSet).join('", "')}");`,
8785
)
8886
}
8987

90-
if (preambleMap.size) {
91-
let preambleResult = ''
92-
for (const [value, key] of preambleMap) {
93-
preambleResult += `const ${key} = ${value}\n`
94-
}
88+
if (templates.length) {
89+
let preambleResult = 'const '
90+
const definedTemplates: Record<string, string> = {}
91+
templates.forEach((template, index) => {
92+
preambleResult += `t${index} = ${
93+
definedTemplates[template] || template
94+
}${templates.length - 1 === index ? ';' : ','}\n`
95+
definedTemplates[template] = `t${index}`
96+
})
9597
statements.unshift(preambleResult)
9698
}
9799

packages/babel/src/transform.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,18 @@ export const transformJSX: VisitNodeFunction<
1919
if (!root || !root.inVaporComponent) return
2020

2121
const isTS = state.filename?.endsWith('tsx')
22-
let { code, helpers, preamble, map } = compile(root.node, {
22+
const { code, map, helpers, templates, delegates } = compile(root.node, {
2323
isTS,
2424
filename: state.filename,
2525
sourceMap: !!state.file.opts.sourceMaps,
2626
source: ' '.repeat(root.node.start || 0) + root.source,
27+
templates: state.templates.slice(),
2728
...state.opts.compile,
2829
})
2930

3031
helpers.forEach((helper) => state.importSet.add(helper))
31-
32-
preamble = preamble.replaceAll(
33-
/(?<=const )t(?=(\d))/g,
34-
`_t${state.preambleIndex}`,
35-
)
36-
code = code.replaceAll(/(?<== )t(?=\d)/g, `_t${state.preambleIndex}`)
37-
state.preambleIndex++
38-
39-
for (const [, key, value] of preamble.matchAll(
40-
/const (_t\d+) = (_template\(.*\))/g,
41-
)) {
42-
const result = state.preambleMap.get(value)
43-
if (result) {
44-
code = code.replaceAll(key, result)
45-
} else {
46-
state.preambleMap.set(value, key)
47-
}
48-
}
49-
50-
for (const [, events] of preamble.matchAll(/_delegateEvents\((.*)\)/g)) {
51-
events.split(', ').forEach((event) => state.delegateEventSet.add(event))
52-
}
32+
delegates.forEach((delegate) => state.delegateEventSet.add(delegate))
33+
state.templates.push(...templates.slice(state.templates.length))
5334

5435
const ast = parse(`(() => {${code}})()`, {
5536
sourceFilename: state.filename,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`transform > transform multiple components 1`] = `
4+
"import { template as _template } from 'vue';
5+
const t0 = _template("<div></div>", true),
6+
t1 = t0,
7+
t2 = t1;
8+
const A = defineComponent(() => {
9+
defineVaporComponent(() => (() => {
10+
const n0 = t0();
11+
return n0;
12+
})());
13+
return () => <div />;
14+
});
15+
const B = defineVaporComponent(() => {
16+
const C = defineComponent(() => <div />);
17+
const D = (() => {
18+
const n0 = t1();
19+
return n0;
20+
})();
21+
return (() => {
22+
const n0 = t2();
23+
return n0;
24+
})();
25+
});"
26+
`;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`transform > transform multiple components 1`] = `
4+
"import { child as _child, delegateEvents as _delegateEvents, template as _template, createIf as _createIf } from 'vue';
5+
import { setNodes as _setNodes } from 'vue-jsx-vapor/runtime';
6+
const t0 = _template("<div> </div>", true),
7+
t1 = _template("<div>Hello</div>"),
8+
t2 = _template("<div>World</div>");
9+
_delegateEvents("click", "dblclick");
10+
const a = (() => {
11+
const n0 = t0();
12+
const x0 = _child(n0);
13+
_setNodes(x0, () => Hello);
14+
n0.$evtclick = e => onClick(e);
15+
return n0;
16+
})();
17+
const b = (() => {
18+
const n0 = _createIf(() => foo, () => {
19+
const n2 = t1();
20+
n2.$evtclick = e => onClick(e);
21+
return n2;
22+
}, () => {
23+
const n4 = t2();
24+
n4.$evtdblclick = e => onDblclick(e);
25+
return n4;
26+
});
27+
return n0;
28+
})();"
29+
`;

packages/babel/test/interop.spec.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,6 @@ describe('transform', () => {
1919
plugins: [[jsx, { interop: true }]],
2020
},
2121
)!
22-
expect(code).toMatchInlineSnapshot(`
23-
"import { template as _template } from 'vue';
24-
const _t00 = _template("<div></div>", true);
25-
const A = defineComponent(() => {
26-
defineVaporComponent(() => (() => {
27-
const n0 = _t00();
28-
return n0;
29-
})());
30-
return () => <div />;
31-
});
32-
const B = defineVaporComponent(() => {
33-
const C = defineComponent(() => <div />);
34-
const D = (() => {
35-
const n0 = _t00();
36-
return n0;
37-
})();
38-
return (() => {
39-
const n0 = _t00();
40-
return n0;
41-
})();
42-
});"
43-
`)
22+
expect(code).matchSnapshot()
4423
})
4524
})

packages/babel/test/transform.spec.ts

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,6 @@ describe('transform', () => {
1212
plugins: [[jsx]],
1313
},
1414
)!
15-
expect(code).toMatchInlineSnapshot(`
16-
"import { child as _child, delegateEvents as _delegateEvents, template as _template, createIf as _createIf } from 'vue';
17-
import { setNodes as _setNodes } from 'vue-jsx-vapor/runtime';
18-
const _t00 = _template("<div> </div>", true);
19-
const _t10 = _template("<div>Hello</div>");
20-
const _t11 = _template("<div>World</div>");
21-
_delegateEvents("click", "dblclick");
22-
const a = (() => {
23-
const n0 = _t00();
24-
const x0 = _child(n0);
25-
_setNodes(x0, () => Hello);
26-
n0.$evtclick = e => onClick(e);
27-
return n0;
28-
})();
29-
const b = (() => {
30-
const n0 = _createIf(() => foo, () => {
31-
const n2 = _t10();
32-
n2.$evtclick = e => onClick(e);
33-
return n2;
34-
}, () => {
35-
const n4 = _t11();
36-
n4.$evtdblclick = e => onDblclick(e);
37-
return n4;
38-
});
39-
return n0;
40-
})();"
41-
`)
15+
expect(code).matchSnapshot()
4216
})
4317
})

packages/compiler/src/compile.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export function compile(
8686

8787
export type CompilerOptions = HackOptions<BaseCompilerOptions> & {
8888
source?: string
89+
templates?: string[]
8990
}
9091
export type TransformPreset = [
9192
NodeTransform[],

packages/compiler/src/generate.ts

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { setTemplateRefIdent } from './generators/templateRef'
55
import {
66
buildCodeFragment,
77
codeFragmentToString,
8-
genCall,
98
INDENT_END,
109
INDENT_START,
1110
NEWLINE,
@@ -20,7 +19,9 @@ import type {
2019
export type CodegenOptions = Omit<
2120
BaseCodegenOptions,
2221
'optimizeImports' | 'inline' | 'bindingMetadata' | 'prefixIdentifiers'
23-
>
22+
> & {
23+
templates?: string[]
24+
}
2425

2526
export class CodegenContext {
2627
options: Required<CodegenOptions>
@@ -84,16 +85,20 @@ export class CodegenContext {
8485
ssr: false,
8586
isTS: false,
8687
inSSR: false,
88+
templates: [],
8789
expressionPlugins: [],
8890
}
8991
this.options = extend(defaultOptions, options)
9092
this.block = ir.block
9193
}
9294
}
9395

94-
export interface VaporCodegenResult extends BaseCodegenResult {
96+
export interface VaporCodegenResult
97+
extends Omit<BaseCodegenResult, 'preamble'> {
9598
ast: RootIRNode
9699
helpers: Set<string>
100+
templates: string[]
101+
delegates: Set<string>
97102
}
98103

99104
// IR -> JS codegen
@@ -115,37 +120,19 @@ export function generate(
115120
push(...genBlockContent(ir.block, context, true))
116121
push(INDENT_END, NEWLINE)
117122

118-
const delegates = genDelegates(context)
119-
const templates = genTemplates(ir.template, ir.rootTemplateIndex, context)
120-
const imports = genHelperImports(context)
121-
const preamble = imports + templates + delegates
123+
if (context.delegates.size) {
124+
context.helper('delegateEvents')
125+
}
126+
const templates = genTemplates(ir.templates, ir.rootTemplateIndex, context)
122127

123128
const [code, map] = codeFragmentToString(frag, context)
124129

125130
return {
126131
code,
127132
ast: ir,
128-
preamble,
129133
map: map && map.toJSON(),
130134
helpers,
135+
templates,
136+
delegates: context.delegates,
131137
}
132138
}
133-
134-
function genDelegates({ delegates, helper }: CodegenContext) {
135-
return delegates.size
136-
? `${genCall(
137-
helper('delegateEvents'),
138-
...Array.from(delegates).map((v) => `"${v}"`),
139-
).join('')}\n`
140-
: ''
141-
}
142-
143-
function genHelperImports({ helpers, options }: CodegenContext) {
144-
let imports = ''
145-
if (helpers.size) {
146-
imports += `import { ${[...helpers]
147-
.map((h) => `${h} as _${h}`)
148-
.join(', ')} } from '${options.runtimeModuleName}';\n`
149-
}
150-
return imports
151-
}

packages/compiler/src/generators/template.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ export function genTemplates(
88
templates: string[],
99
rootIndex: number | undefined,
1010
{ helper }: CodegenContext,
11-
): string {
12-
return templates
13-
.map(
14-
(template, i) =>
15-
`const t${i} = ${helper('template')}(${JSON.stringify(
11+
): string[] {
12+
return templates.map((template, i) =>
13+
template.startsWith('_template')
14+
? template
15+
: `${helper('template')}(${JSON.stringify(
1616
template,
17-
)}${i === rootIndex ? ', true' : ''})\n`,
18-
)
19-
.join('')
17+
)}${i === rootIndex ? ', true' : ''})`,
18+
)
2019
}
2120

2221
export function genSelf(

packages/compiler/src/ir/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface RootIRNode {
6464
type: IRNodeTypes.ROOT
6565
node: RootNode
6666
source: string
67-
template: string[]
67+
templates: string[]
6868
rootTemplateIndex?: number
6969
component: Set<string>
7070
directive: Set<string>

0 commit comments

Comments
 (0)