@tanstack/router-plugin 1.98.1 → 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.
@@ -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
- if (prop.key.name === 'component') {
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
- // Prepend the import statement to the program along with the importer function
131
- // Check to see if lazyRouteComponent is already imported before attempting
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
- if (
147
- !hasImportedOrDefinedIdentifier(
148
- '$$splitComponentImporter',
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($$splitComponentImporter, 'component', () => Route.ssr)`,
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 DummyComponent() { return null }`,
222
+ `export function TSRDummyComponent() { return null }`,
165
223
  )(),
166
224
  ])
167
-
168
- found = true
169
225
  }
170
- } else if (prop.key.name === 'loader') {
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
- // Prepend the import statement to the program along with the importer function
195
- if (!hasImportedOrDefinedIdentifier('lazyFn')) {
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
- prop.value = template.expression(
216
- `lazyFn($$splitLoaderImporter, 'loader')`,
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
- found = true
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 splitNodesByType: Record<SplitNodeType, t.Node | undefined> = {
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
- splitNodeTypes.forEach((splitType) => {
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
- splitNodesByType[splitType] = prop.value
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
- splitNodeTypes.forEach((splitType) => {
357
- let splitNode = splitNodesByType[splitType]
416
+ SPLIT_ROUTE_IDENT_NODES.forEach((SPLIT_TYPE) => {
417
+ const splitKey = trackedNodesToSplitByType[SPLIT_TYPE]
358
418
 
359
- if (!splitNode) {
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(splitType),
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(splitType),
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(splitType),
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(t.identifier(splitType), splitNode.init),
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 "${splitType}" in the node type "${splitNode.type}"`,
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 "${splitType}" in the node type "${splitNode.type}" as no statement was found in the program body`,
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(t.identifier(splitType), expression),
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 "${splitType}" in the node type "${splitNode.type}"`,
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(splitType),
467
- t.identifier(splitType),
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
  ])