@tanstack/router-plugin 1.98.0 → 1.98.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/code-splitter/compilers.cjs +122 -68
- package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
- package/dist/esm/core/code-splitter/compilers.js +122 -68
- package/dist/esm/core/code-splitter/compilers.js.map +1 -1
- package/package.json +3 -3
- package/src/core/code-splitter/compilers.ts +154 -85
|
@@ -47,6 +47,38 @@ function removeSplitSearchParamFromFilename(filename: string) {
|
|
|
47
47
|
return bareFilename!
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
type SplitRouteIdentNodes = 'component' | 'loader'
|
|
51
|
+
type SplitNodeMeta = {
|
|
52
|
+
routeIdent: SplitRouteIdentNodes
|
|
53
|
+
splitStrategy: 'normal' | 'react-component'
|
|
54
|
+
localImporterIdent: string
|
|
55
|
+
exporterIdent: string
|
|
56
|
+
localExporterIdent: string
|
|
57
|
+
}
|
|
58
|
+
const SPLIT_NOES_CONFIG = new Map<SplitRouteIdentNodes, SplitNodeMeta>([
|
|
59
|
+
[
|
|
60
|
+
'component',
|
|
61
|
+
{
|
|
62
|
+
routeIdent: 'component',
|
|
63
|
+
localImporterIdent: '$$splitComponentImporter', // const $$splitComponentImporter = () => import('...')
|
|
64
|
+
splitStrategy: 'react-component',
|
|
65
|
+
localExporterIdent: 'SplitComponent', // const SplitComponent = ...
|
|
66
|
+
exporterIdent: 'component', // export { SplitComponent as component }
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
'loader',
|
|
71
|
+
{
|
|
72
|
+
routeIdent: 'loader',
|
|
73
|
+
localImporterIdent: '$$splitLoaderImporter', // const $$splitLoaderImporter = () => import('...')
|
|
74
|
+
splitStrategy: 'normal',
|
|
75
|
+
localExporterIdent: 'SplitLoader', // const SplitLoader = ...
|
|
76
|
+
exporterIdent: 'loader', // export { SplitLoader as loader }
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
])
|
|
80
|
+
const SPLIT_ROUTE_IDENT_NODES = [...SPLIT_NOES_CONFIG.keys()] as const
|
|
81
|
+
|
|
50
82
|
export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
51
83
|
const ast = parseAst(opts)
|
|
52
84
|
|
|
@@ -93,8 +125,6 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
93
125
|
path.parentPath.node.arguments[0],
|
|
94
126
|
)
|
|
95
127
|
|
|
96
|
-
let found = false
|
|
97
|
-
|
|
98
128
|
const hasImportedOrDefinedIdentifier = (name: string) => {
|
|
99
129
|
return programPath.scope.hasBinding(name)
|
|
100
130
|
}
|
|
@@ -103,7 +133,19 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
103
133
|
options.properties.forEach((prop) => {
|
|
104
134
|
if (t.isObjectProperty(prop)) {
|
|
105
135
|
if (t.isIdentifier(prop.key)) {
|
|
106
|
-
|
|
136
|
+
const key = prop.key.name
|
|
137
|
+
// find key in nodeSplitConfig
|
|
138
|
+
const isNodeConfigAvailable = SPLIT_NOES_CONFIG.has(
|
|
139
|
+
key as any,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if (!isNodeConfigAvailable) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const splitNodeMeta = SPLIT_NOES_CONFIG.get(key as any)!
|
|
147
|
+
|
|
148
|
+
if (splitNodeMeta.splitStrategy === 'react-component') {
|
|
107
149
|
const value = prop.value
|
|
108
150
|
|
|
109
151
|
let shouldSplit = true
|
|
@@ -126,48 +168,64 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
126
168
|
}
|
|
127
169
|
}
|
|
128
170
|
|
|
129
|
-
if (shouldSplit) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// to import it again
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
!hasImportedOrDefinedIdentifier(
|
|
136
|
-
'lazyRouteComponent',
|
|
137
|
-
)
|
|
138
|
-
) {
|
|
139
|
-
programPath.unshiftContainer('body', [
|
|
140
|
-
template.statement(
|
|
141
|
-
`import { lazyRouteComponent } from '@tanstack/react-router'`,
|
|
142
|
-
)(),
|
|
143
|
-
])
|
|
144
|
-
}
|
|
171
|
+
if (!shouldSplit) {
|
|
172
|
+
return
|
|
173
|
+
}
|
|
145
174
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
) {
|
|
151
|
-
programPath.unshiftContainer('body', [
|
|
152
|
-
template.statement(
|
|
153
|
-
`const $$splitComponentImporter = () => import('${splitUrl}')`,
|
|
154
|
-
)(),
|
|
155
|
-
])
|
|
156
|
-
}
|
|
175
|
+
// Prepend the import statement to the program along with the importer function
|
|
176
|
+
// Check to see if lazyRouteComponent is already imported before attempting
|
|
177
|
+
// to import it again
|
|
157
178
|
|
|
179
|
+
if (
|
|
180
|
+
!hasImportedOrDefinedIdentifier(
|
|
181
|
+
'lazyRouteComponent',
|
|
182
|
+
)
|
|
183
|
+
) {
|
|
184
|
+
programPath.unshiftContainer('body', [
|
|
185
|
+
template.statement(
|
|
186
|
+
`import { lazyRouteComponent } from '@tanstack/react-router'`,
|
|
187
|
+
)(),
|
|
188
|
+
])
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Check to see if the importer function is already defined
|
|
192
|
+
// If not, define it with the dynamic import statement
|
|
193
|
+
if (
|
|
194
|
+
!hasImportedOrDefinedIdentifier(
|
|
195
|
+
splitNodeMeta.localImporterIdent,
|
|
196
|
+
)
|
|
197
|
+
) {
|
|
198
|
+
programPath.unshiftContainer('body', [
|
|
199
|
+
template.statement(
|
|
200
|
+
`const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`,
|
|
201
|
+
)(),
|
|
202
|
+
])
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// If it's a component, we need to pass the function to check the Route.ssr value
|
|
206
|
+
if (key === 'component') {
|
|
207
|
+
prop.value = template.expression(
|
|
208
|
+
`lazyRouteComponent(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}', () => Route.ssr)`,
|
|
209
|
+
)()
|
|
210
|
+
} else {
|
|
158
211
|
prop.value = template.expression(
|
|
159
|
-
`lazyRouteComponent(
|
|
212
|
+
`lazyRouteComponent(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`,
|
|
160
213
|
)()
|
|
214
|
+
}
|
|
161
215
|
|
|
216
|
+
// If the TSRDummyComponent is not defined, define it
|
|
217
|
+
if (
|
|
218
|
+
!hasImportedOrDefinedIdentifier('TSRDummyComponent')
|
|
219
|
+
) {
|
|
162
220
|
programPath.pushContainer('body', [
|
|
163
221
|
template.statement(
|
|
164
|
-
`function
|
|
222
|
+
`export function TSRDummyComponent() { return null }`,
|
|
165
223
|
)(),
|
|
166
224
|
])
|
|
167
|
-
|
|
168
|
-
found = true
|
|
169
225
|
}
|
|
170
|
-
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (splitNodeMeta.splitStrategy === 'normal') {
|
|
171
229
|
const value = prop.value
|
|
172
230
|
|
|
173
231
|
let shouldSplit = true
|
|
@@ -190,34 +248,38 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
190
248
|
}
|
|
191
249
|
}
|
|
192
250
|
|
|
193
|
-
if (shouldSplit) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
programPath.unshiftContainer('body', [
|
|
197
|
-
template.smart(
|
|
198
|
-
`import { lazyFn } from '@tanstack/react-router'`,
|
|
199
|
-
)() as t.Statement,
|
|
200
|
-
])
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
!hasImportedOrDefinedIdentifier(
|
|
205
|
-
'$$splitLoaderImporter',
|
|
206
|
-
)
|
|
207
|
-
) {
|
|
208
|
-
programPath.unshiftContainer('body', [
|
|
209
|
-
template.statement(
|
|
210
|
-
`const $$splitLoaderImporter = () => import('${splitUrl}')`,
|
|
211
|
-
)(),
|
|
212
|
-
])
|
|
213
|
-
}
|
|
251
|
+
if (!shouldSplit) {
|
|
252
|
+
return
|
|
253
|
+
}
|
|
214
254
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
255
|
+
// Prepend the import statement to the program along with the importer function
|
|
256
|
+
if (!hasImportedOrDefinedIdentifier('lazyFn')) {
|
|
257
|
+
programPath.unshiftContainer(
|
|
258
|
+
'body',
|
|
259
|
+
template.smart(
|
|
260
|
+
`import { lazyFn } from '@tanstack/react-router'`,
|
|
261
|
+
)(),
|
|
262
|
+
)
|
|
263
|
+
}
|
|
218
264
|
|
|
219
|
-
|
|
265
|
+
// Check to see if the importer function is already defined
|
|
266
|
+
// If not, define it with the dynamic import statement
|
|
267
|
+
if (
|
|
268
|
+
!hasImportedOrDefinedIdentifier(
|
|
269
|
+
splitNodeMeta.localImporterIdent,
|
|
270
|
+
)
|
|
271
|
+
) {
|
|
272
|
+
programPath.unshiftContainer('body', [
|
|
273
|
+
template.statement(
|
|
274
|
+
`const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`,
|
|
275
|
+
)(),
|
|
276
|
+
])
|
|
220
277
|
}
|
|
278
|
+
|
|
279
|
+
// Add the lazyFn call with the dynamic import to the prop value
|
|
280
|
+
prop.value = template.expression(
|
|
281
|
+
`lazyFn(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`,
|
|
282
|
+
)()
|
|
221
283
|
}
|
|
222
284
|
}
|
|
223
285
|
}
|
|
@@ -225,12 +287,6 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
225
287
|
programPath.scope.crawl()
|
|
226
288
|
})
|
|
227
289
|
}
|
|
228
|
-
|
|
229
|
-
if (found as boolean) {
|
|
230
|
-
programPath.pushContainer('body', [
|
|
231
|
-
template.statement(`function TSR_Dummy_Component() {}`)(),
|
|
232
|
-
])
|
|
233
|
-
}
|
|
234
290
|
}
|
|
235
291
|
},
|
|
236
292
|
},
|
|
@@ -271,9 +327,6 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
|
|
|
271
327
|
})
|
|
272
328
|
}
|
|
273
329
|
|
|
274
|
-
const splitNodeTypes = ['component', 'loader'] as const
|
|
275
|
-
type SplitNodeType = (typeof splitNodeTypes)[number]
|
|
276
|
-
|
|
277
330
|
export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
278
331
|
const ast = parseAst(opts)
|
|
279
332
|
|
|
@@ -284,7 +337,10 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
284
337
|
enter(programPath, programState) {
|
|
285
338
|
const state = programState as unknown as State
|
|
286
339
|
|
|
287
|
-
const
|
|
340
|
+
const trackedNodesToSplitByType: Record<
|
|
341
|
+
SplitRouteIdentNodes,
|
|
342
|
+
{ node: t.Node | undefined; meta: SplitNodeMeta } | undefined
|
|
343
|
+
> = {
|
|
288
344
|
component: undefined,
|
|
289
345
|
loader: undefined,
|
|
290
346
|
}
|
|
@@ -315,7 +371,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
315
371
|
if (t.isObjectExpression(options)) {
|
|
316
372
|
options.properties.forEach((prop) => {
|
|
317
373
|
if (t.isObjectProperty(prop)) {
|
|
318
|
-
|
|
374
|
+
SPLIT_ROUTE_IDENT_NODES.forEach((splitType) => {
|
|
319
375
|
if (
|
|
320
376
|
!t.isIdentifier(prop.key) ||
|
|
321
377
|
prop.key.name !== splitType
|
|
@@ -338,7 +394,11 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
338
394
|
if (isExported && t.isIdentifier(value)) {
|
|
339
395
|
removeExports(ast, value)
|
|
340
396
|
} else {
|
|
341
|
-
|
|
397
|
+
const meta = SPLIT_NOES_CONFIG.get(splitType)!
|
|
398
|
+
trackedNodesToSplitByType[splitType] = {
|
|
399
|
+
node: prop.value,
|
|
400
|
+
meta,
|
|
401
|
+
}
|
|
342
402
|
}
|
|
343
403
|
})
|
|
344
404
|
}
|
|
@@ -353,13 +413,16 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
353
413
|
state,
|
|
354
414
|
)
|
|
355
415
|
|
|
356
|
-
|
|
357
|
-
|
|
416
|
+
SPLIT_ROUTE_IDENT_NODES.forEach((SPLIT_TYPE) => {
|
|
417
|
+
const splitKey = trackedNodesToSplitByType[SPLIT_TYPE]
|
|
358
418
|
|
|
359
|
-
if (!
|
|
419
|
+
if (!splitKey) {
|
|
360
420
|
return
|
|
361
421
|
}
|
|
362
422
|
|
|
423
|
+
let splitNode = splitKey.node
|
|
424
|
+
const splitMeta = splitKey.meta
|
|
425
|
+
|
|
363
426
|
while (t.isIdentifier(splitNode)) {
|
|
364
427
|
const binding = programPath.scope.getBinding(splitNode.name)
|
|
365
428
|
splitNode = binding?.path.node
|
|
@@ -372,7 +435,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
372
435
|
'body',
|
|
373
436
|
t.variableDeclaration('const', [
|
|
374
437
|
t.variableDeclarator(
|
|
375
|
-
t.identifier(
|
|
438
|
+
t.identifier(splitMeta.localExporterIdent),
|
|
376
439
|
t.functionExpression(
|
|
377
440
|
splitNode.id || null, // Anonymize the function expression
|
|
378
441
|
splitNode.params,
|
|
@@ -391,7 +454,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
391
454
|
'body',
|
|
392
455
|
t.variableDeclaration('const', [
|
|
393
456
|
t.variableDeclarator(
|
|
394
|
-
t.identifier(
|
|
457
|
+
t.identifier(splitMeta.localExporterIdent),
|
|
395
458
|
splitNode as any,
|
|
396
459
|
),
|
|
397
460
|
]),
|
|
@@ -404,7 +467,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
404
467
|
'body',
|
|
405
468
|
t.variableDeclaration('const', [
|
|
406
469
|
t.variableDeclarator(
|
|
407
|
-
t.identifier(
|
|
470
|
+
t.identifier(splitMeta.localExporterIdent),
|
|
408
471
|
splitNode.local,
|
|
409
472
|
),
|
|
410
473
|
]),
|
|
@@ -413,7 +476,10 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
413
476
|
programPath.pushContainer(
|
|
414
477
|
'body',
|
|
415
478
|
t.variableDeclaration('const', [
|
|
416
|
-
t.variableDeclarator(
|
|
479
|
+
t.variableDeclarator(
|
|
480
|
+
t.identifier(splitMeta.localExporterIdent),
|
|
481
|
+
splitNode.init,
|
|
482
|
+
),
|
|
417
483
|
]),
|
|
418
484
|
)
|
|
419
485
|
} else if (t.isCallExpression(splitNode)) {
|
|
@@ -422,7 +488,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
422
488
|
|
|
423
489
|
if (!splitNodeAst) {
|
|
424
490
|
throw new Error(
|
|
425
|
-
`Failed to parse the generated code for "${
|
|
491
|
+
`Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`,
|
|
426
492
|
)
|
|
427
493
|
}
|
|
428
494
|
|
|
@@ -430,7 +496,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
430
496
|
|
|
431
497
|
if (!statement) {
|
|
432
498
|
throw new Error(
|
|
433
|
-
`Failed to parse the generated code for "${
|
|
499
|
+
`Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}" as no statement was found in the program body`,
|
|
434
500
|
)
|
|
435
501
|
}
|
|
436
502
|
|
|
@@ -439,12 +505,15 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
439
505
|
programPath.pushContainer(
|
|
440
506
|
'body',
|
|
441
507
|
t.variableDeclaration('const', [
|
|
442
|
-
t.variableDeclarator(
|
|
508
|
+
t.variableDeclarator(
|
|
509
|
+
t.identifier(splitMeta.localExporterIdent),
|
|
510
|
+
expression,
|
|
511
|
+
),
|
|
443
512
|
]),
|
|
444
513
|
)
|
|
445
514
|
} else {
|
|
446
515
|
throw new Error(
|
|
447
|
-
`Unexpected expression type encounter for "${
|
|
516
|
+
`Unexpected expression type encounter for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`,
|
|
448
517
|
)
|
|
449
518
|
}
|
|
450
519
|
} else {
|
|
@@ -463,8 +532,8 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) {
|
|
|
463
532
|
programPath.pushContainer('body', [
|
|
464
533
|
t.exportNamedDeclaration(null, [
|
|
465
534
|
t.exportSpecifier(
|
|
466
|
-
t.identifier(
|
|
467
|
-
t.identifier(
|
|
535
|
+
t.identifier(splitMeta.localExporterIdent), // local variable name
|
|
536
|
+
t.identifier(splitMeta.exporterIdent), // as what name it should be exported as
|
|
468
537
|
),
|
|
469
538
|
]),
|
|
470
539
|
])
|