@tanstack/router-plugin 1.124.0 → 1.125.0

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.
Files changed (40) hide show
  1. package/dist/cjs/core/code-splitter/compilers.cjs +43 -21
  2. package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
  3. package/dist/cjs/core/code-splitter/compilers.d.cts +3 -2
  4. package/dist/cjs/core/config.cjs +11 -1
  5. package/dist/cjs/core/config.cjs.map +1 -1
  6. package/dist/cjs/core/config.d.cts +45 -0
  7. package/dist/cjs/core/router-code-splitter-plugin.cjs +20 -4
  8. package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
  9. package/dist/cjs/core/router-generator-plugin.cjs +6 -3
  10. package/dist/cjs/core/router-generator-plugin.cjs.map +1 -1
  11. package/dist/cjs/core/router-hmr-plugin.cjs +25 -2
  12. package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
  13. package/dist/cjs/core/router-hmr-plugin.d.cts +1 -6
  14. package/dist/cjs/esbuild.d.cts +20 -0
  15. package/dist/cjs/rspack.d.cts +20 -0
  16. package/dist/cjs/vite.d.cts +25 -0
  17. package/dist/cjs/webpack.d.cts +20 -0
  18. package/dist/esm/core/code-splitter/compilers.d.ts +3 -2
  19. package/dist/esm/core/code-splitter/compilers.js +43 -21
  20. package/dist/esm/core/code-splitter/compilers.js.map +1 -1
  21. package/dist/esm/core/config.d.ts +45 -0
  22. package/dist/esm/core/config.js +11 -1
  23. package/dist/esm/core/config.js.map +1 -1
  24. package/dist/esm/core/router-code-splitter-plugin.js +20 -4
  25. package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
  26. package/dist/esm/core/router-generator-plugin.js +6 -3
  27. package/dist/esm/core/router-generator-plugin.js.map +1 -1
  28. package/dist/esm/core/router-hmr-plugin.d.ts +1 -6
  29. package/dist/esm/core/router-hmr-plugin.js +25 -2
  30. package/dist/esm/core/router-hmr-plugin.js.map +1 -1
  31. package/dist/esm/esbuild.d.ts +20 -0
  32. package/dist/esm/rspack.d.ts +20 -0
  33. package/dist/esm/vite.d.ts +25 -0
  34. package/dist/esm/webpack.d.ts +20 -0
  35. package/package.json +4 -4
  36. package/src/core/code-splitter/compilers.ts +52 -35
  37. package/src/core/config.ts +25 -0
  38. package/src/core/router-code-splitter-plugin.ts +20 -3
  39. package/src/core/router-generator-plugin.ts +6 -7
  40. package/src/core/router-hmr-plugin.ts +27 -3
@@ -1 +1 @@
1
- {"version":3,"file":"router-hmr-plugin.js","sources":["../../../src/core/router-hmr-plugin.ts"],"sourcesContent":["import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'\nimport { routeHmrStatement } from './route-hmr-statement'\nimport { debug } from './utils'\nimport type { Config } from './config'\nimport type { UnpluginFactory } from 'unplugin'\n\n/**\n * This plugin adds HMR support for file routes.\n * It is only added to the composed plugin in dev when autoCodeSplitting is disabled, since the code splitting plugin\n * handles HMR for code-split routes itself.\n */\nexport const unpluginRouterHmrFactory: UnpluginFactory<\n Partial<Config> | undefined\n> = () => {\n return {\n name: 'tanstack-router:hmr',\n enforce: 'pre',\n transform: {\n filter: {\n // this is necessary for webpack / rspack to avoid matching .html files\n id: /\\.(m|c)?(j|t)sx?$/,\n code: 'createFileRoute(',\n },\n handler(code, id) {\n if (!globalThis.TSR_ROUTES_BY_ID_MAP?.has(id)) {\n return null\n }\n\n if (debug) console.info('Adding HMR handling to route ', id)\n\n const ast = parseAst({ code })\n ast.program.body.push(routeHmrStatement)\n const result = generateFromAst(ast, {\n sourceMaps: true,\n filename: id,\n sourceFileName: id,\n })\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n return result\n },\n },\n }\n}\n"],"names":[],"mappings":";;;AAWO,MAAM,2BAET,MAAM;AACD,SAAA;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,MACT,QAAQ;AAAA;AAAA,QAEN,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,MAAM,IAAI;;AAChB,YAAI,GAAC,gBAAW,yBAAX,mBAAiC,IAAI,MAAK;AACtC,iBAAA;AAAA,QAAA;AAGT,YAAI,MAAO,SAAQ,KAAK,iCAAiC,EAAE;AAE3D,cAAM,MAAM,SAAS,EAAE,MAAM;AACzB,YAAA,QAAQ,KAAK,KAAK,iBAAiB;AACjC,cAAA,SAAS,gBAAgB,KAAK;AAAA,UAClC,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,gBAAgB;AAAA,QAAA,CACjB;AACD,YAAI,OAAO;AACD,kBAAA,MAAM,OAAO,IAAI;AACzB,kBAAQ,IAAI,aAAa,OAAO,OAAO,MAAM;AAAA,QAAA;AAExC,eAAA;AAAA,MAAA;AAAA,IACT;AAAA,EAEJ;AACF;"}
1
+ {"version":3,"file":"router-hmr-plugin.js","sources":["../../../src/core/router-hmr-plugin.ts"],"sourcesContent":["import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'\nimport { routeHmrStatement } from './route-hmr-statement'\nimport { debug } from './utils'\nimport { getConfig } from './config'\nimport type { UnpluginFactory } from 'unplugin'\nimport type { Config } from './config'\n\n/**\n * This plugin adds HMR support for file routes.\n * It is only added to the composed plugin in dev when autoCodeSplitting is disabled, since the code splitting plugin\n * handles HMR for code-split routes itself.\n */\n\nconst includeCode = [\n 'createFileRoute(',\n 'createRootRoute(',\n 'createRootRouteWithContext(',\n]\nexport const unpluginRouterHmrFactory: UnpluginFactory<\n Partial<Config> | undefined\n> = (options = {}) => {\n let ROOT: string = process.cwd()\n let userConfig = options as Config\n\n return {\n name: 'tanstack-router:hmr',\n enforce: 'pre',\n transform: {\n filter: {\n // this is necessary for webpack / rspack to avoid matching .html files\n id: /\\.(m|c)?(j|t)sx?$/,\n code: {\n include: includeCode,\n },\n },\n handler(code, id) {\n if (!globalThis.TSR_ROUTES_BY_ID_MAP?.has(id)) {\n return null\n }\n\n if (debug) console.info('Adding HMR handling to route ', id)\n\n const ast = parseAst({ code })\n ast.program.body.push(routeHmrStatement)\n const result = generateFromAst(ast, {\n sourceMaps: true,\n filename: id,\n sourceFileName: id,\n })\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n return result\n },\n },\n vite: {\n configResolved(config) {\n ROOT = config.root\n userConfig = getConfig(options, ROOT)\n },\n applyToEnvironment(environment) {\n if (userConfig.plugin?.vite?.environmentName) {\n return userConfig.plugin.vite.environmentName === environment.name\n }\n return true\n },\n },\n }\n}\n"],"names":[],"mappings":";;;;AAaA,MAAM,cAAc;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF;AACO,MAAM,2BAET,CAAC,UAAU,OAAO;AAChB,MAAA,OAAe,QAAQ,IAAI;AAC/B,MAAI,aAAa;AAEV,SAAA;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,MACT,QAAQ;AAAA;AAAA,QAEN,IAAI;AAAA,QACJ,MAAM;AAAA,UACJ,SAAS;AAAA,QAAA;AAAA,MAEb;AAAA,MACA,QAAQ,MAAM,IAAI;;AAChB,YAAI,GAAC,gBAAW,yBAAX,mBAAiC,IAAI,MAAK;AACtC,iBAAA;AAAA,QAAA;AAGT,YAAI,MAAO,SAAQ,KAAK,iCAAiC,EAAE;AAE3D,cAAM,MAAM,SAAS,EAAE,MAAM;AACzB,YAAA,QAAQ,KAAK,KAAK,iBAAiB;AACjC,cAAA,SAAS,gBAAgB,KAAK;AAAA,UAClC,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,gBAAgB;AAAA,QAAA,CACjB;AACD,YAAI,OAAO;AACD,kBAAA,MAAM,OAAO,IAAI;AACzB,kBAAQ,IAAI,aAAa,OAAO,OAAO,MAAM;AAAA,QAAA;AAExC,eAAA;AAAA,MAAA;AAAA,IAEX;AAAA,IACA,MAAM;AAAA,MACJ,eAAe,QAAQ;AACrB,eAAO,OAAO;AACD,qBAAA,UAAU,SAAS,IAAI;AAAA,MACtC;AAAA,MACA,mBAAmB,aAAa;;AAC1B,aAAA,sBAAW,WAAX,mBAAmB,SAAnB,mBAAyB,iBAAiB;AAC5C,iBAAO,WAAW,OAAO,KAAK,oBAAoB,YAAY;AAAA,QAAA;AAEzD,eAAA;AAAA,MAAA;AAAA,IACT;AAAA,EAEJ;AACF;"}
@@ -26,6 +26,11 @@ declare const TanStackRouterGeneratorEsbuild: (options?: Partial<{
26
26
  tmpDir: string;
27
27
  enableRouteGeneration?: boolean | undefined;
28
28
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
29
+ plugin?: {
30
+ vite?: {
31
+ environmentName?: string | undefined;
32
+ } | undefined;
33
+ } | undefined;
29
34
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
30
35
  routeFilePrefix?: string | undefined;
31
36
  routeFileIgnorePattern?: string | undefined;
@@ -68,6 +73,11 @@ declare const TanStackRouterCodeSplitterEsbuild: (options?: Partial<{
68
73
  tmpDir: string;
69
74
  enableRouteGeneration?: boolean | undefined;
70
75
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
76
+ plugin?: {
77
+ vite?: {
78
+ environmentName?: string | undefined;
79
+ } | undefined;
80
+ } | undefined;
71
81
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
72
82
  routeFilePrefix?: string | undefined;
73
83
  routeFileIgnorePattern?: string | undefined;
@@ -110,6 +120,11 @@ declare const TanStackRouterEsbuild: (options?: Partial<{
110
120
  tmpDir: string;
111
121
  enableRouteGeneration?: boolean | undefined;
112
122
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
123
+ plugin?: {
124
+ vite?: {
125
+ environmentName?: string | undefined;
126
+ } | undefined;
127
+ } | undefined;
113
128
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
114
129
  routeFilePrefix?: string | undefined;
115
130
  routeFileIgnorePattern?: string | undefined;
@@ -143,6 +158,11 @@ declare const tanstackRouter: (options?: Partial<{
143
158
  tmpDir: string;
144
159
  enableRouteGeneration?: boolean | undefined;
145
160
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
161
+ plugin?: {
162
+ vite?: {
163
+ environmentName?: string | undefined;
164
+ } | undefined;
165
+ } | undefined;
146
166
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
147
167
  routeFilePrefix?: string | undefined;
148
168
  routeFileIgnorePattern?: string | undefined;
@@ -30,6 +30,11 @@ declare const TanStackRouterGeneratorRspack: (options?: Partial<{
30
30
  tmpDir: string;
31
31
  enableRouteGeneration?: boolean | undefined;
32
32
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
33
+ plugin?: {
34
+ vite?: {
35
+ environmentName?: string | undefined;
36
+ } | undefined;
37
+ } | undefined;
33
38
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
34
39
  routeFilePrefix?: string | undefined;
35
40
  routeFileIgnorePattern?: string | undefined;
@@ -76,6 +81,11 @@ declare const TanStackRouterCodeSplitterRspack: (options?: Partial<{
76
81
  tmpDir: string;
77
82
  enableRouteGeneration?: boolean | undefined;
78
83
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
84
+ plugin?: {
85
+ vite?: {
86
+ environmentName?: string | undefined;
87
+ } | undefined;
88
+ } | undefined;
79
89
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
80
90
  routeFilePrefix?: string | undefined;
81
91
  routeFileIgnorePattern?: string | undefined;
@@ -122,6 +132,11 @@ declare const TanStackRouterRspack: (options?: Partial<{
122
132
  tmpDir: string;
123
133
  enableRouteGeneration?: boolean | undefined;
124
134
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
135
+ plugin?: {
136
+ vite?: {
137
+ environmentName?: string | undefined;
138
+ } | undefined;
139
+ } | undefined;
125
140
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
126
141
  routeFilePrefix?: string | undefined;
127
142
  routeFileIgnorePattern?: string | undefined;
@@ -155,6 +170,11 @@ declare const tanstackRouter: (options?: Partial<{
155
170
  tmpDir: string;
156
171
  enableRouteGeneration?: boolean | undefined;
157
172
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
173
+ plugin?: {
174
+ vite?: {
175
+ environmentName?: string | undefined;
176
+ } | undefined;
177
+ } | undefined;
158
178
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
159
179
  routeFilePrefix?: string | undefined;
160
180
  routeFileIgnorePattern?: string | undefined;
@@ -17,6 +17,11 @@ declare const tanstackRouterAutoImport: (options?: Partial<{
17
17
  tmpDir: string;
18
18
  enableRouteGeneration?: boolean | undefined;
19
19
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
20
+ plugin?: {
21
+ vite?: {
22
+ environmentName?: string | undefined;
23
+ } | undefined;
24
+ } | undefined;
20
25
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
21
26
  routeFilePrefix?: string | undefined;
22
27
  routeFileIgnorePattern?: string | undefined;
@@ -59,6 +64,11 @@ declare const tanstackRouterGenerator: (options?: Partial<{
59
64
  tmpDir: string;
60
65
  enableRouteGeneration?: boolean | undefined;
61
66
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
67
+ plugin?: {
68
+ vite?: {
69
+ environmentName?: string | undefined;
70
+ } | undefined;
71
+ } | undefined;
62
72
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
63
73
  routeFilePrefix?: string | undefined;
64
74
  routeFileIgnorePattern?: string | undefined;
@@ -101,6 +111,11 @@ declare const tanStackRouterCodeSplitter: (options?: Partial<{
101
111
  tmpDir: string;
102
112
  enableRouteGeneration?: boolean | undefined;
103
113
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
114
+ plugin?: {
115
+ vite?: {
116
+ environmentName?: string | undefined;
117
+ } | undefined;
118
+ } | undefined;
104
119
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
105
120
  routeFilePrefix?: string | undefined;
106
121
  routeFileIgnorePattern?: string | undefined;
@@ -143,6 +158,11 @@ declare const tanstackRouter: (options?: Partial<{
143
158
  tmpDir: string;
144
159
  enableRouteGeneration?: boolean | undefined;
145
160
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
161
+ plugin?: {
162
+ vite?: {
163
+ environmentName?: string | undefined;
164
+ } | undefined;
165
+ } | undefined;
146
166
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
147
167
  routeFilePrefix?: string | undefined;
148
168
  routeFileIgnorePattern?: string | undefined;
@@ -179,6 +199,11 @@ declare const TanStackRouterVite: (options?: Partial<{
179
199
  tmpDir: string;
180
200
  enableRouteGeneration?: boolean | undefined;
181
201
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
202
+ plugin?: {
203
+ vite?: {
204
+ environmentName?: string | undefined;
205
+ } | undefined;
206
+ } | undefined;
182
207
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
183
208
  routeFilePrefix?: string | undefined;
184
209
  routeFileIgnorePattern?: string | undefined;
@@ -26,6 +26,11 @@ declare const TanStackRouterGeneratorWebpack: (options?: Partial<{
26
26
  tmpDir: string;
27
27
  enableRouteGeneration?: boolean | undefined;
28
28
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
29
+ plugin?: {
30
+ vite?: {
31
+ environmentName?: string | undefined;
32
+ } | undefined;
33
+ } | undefined;
29
34
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
30
35
  routeFilePrefix?: string | undefined;
31
36
  routeFileIgnorePattern?: string | undefined;
@@ -68,6 +73,11 @@ declare const TanStackRouterCodeSplitterWebpack: (options?: Partial<{
68
73
  tmpDir: string;
69
74
  enableRouteGeneration?: boolean | undefined;
70
75
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
76
+ plugin?: {
77
+ vite?: {
78
+ environmentName?: string | undefined;
79
+ } | undefined;
80
+ } | undefined;
71
81
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
72
82
  routeFilePrefix?: string | undefined;
73
83
  routeFileIgnorePattern?: string | undefined;
@@ -110,6 +120,11 @@ declare const TanStackRouterWebpack: (options?: Partial<{
110
120
  tmpDir: string;
111
121
  enableRouteGeneration?: boolean | undefined;
112
122
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
123
+ plugin?: {
124
+ vite?: {
125
+ environmentName?: string | undefined;
126
+ } | undefined;
127
+ } | undefined;
113
128
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
114
129
  routeFilePrefix?: string | undefined;
115
130
  routeFileIgnorePattern?: string | undefined;
@@ -143,6 +158,11 @@ declare const tanstackRouter: (options?: Partial<{
143
158
  tmpDir: string;
144
159
  enableRouteGeneration?: boolean | undefined;
145
160
  codeSplittingOptions?: import('./core/config.js').CodeSplittingOptions | undefined;
161
+ plugin?: {
162
+ vite?: {
163
+ environmentName?: string | undefined;
164
+ } | undefined;
165
+ } | undefined;
146
166
  virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
147
167
  routeFilePrefix?: string | undefined;
148
168
  routeFileIgnorePattern?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-plugin",
3
- "version": "1.124.0",
3
+ "version": "1.125.0",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -97,9 +97,9 @@
97
97
  "chokidar": "^3.6.0",
98
98
  "unplugin": "^2.1.2",
99
99
  "zod": "^3.24.2",
100
- "@tanstack/router-core": "^1.124.0",
101
- "@tanstack/router-generator": "1.124.0",
100
+ "@tanstack/router-core": "^1.125.0",
102
101
  "@tanstack/router-utils": "1.121.21",
102
+ "@tanstack/router-generator": "1.125.0",
103
103
  "@tanstack/virtual-file-routes": "^1.121.21"
104
104
  },
105
105
  "devDependencies": {
@@ -112,7 +112,7 @@
112
112
  "vite": ">=5.0.0 || >=6.0.0",
113
113
  "vite-plugin-solid": "^2.11.2",
114
114
  "webpack": ">=5.92.0",
115
- "@tanstack/react-router": "^1.124.0"
115
+ "@tanstack/react-router": "^1.125.0"
116
116
  },
117
117
  "peerDependenciesMeta": {
118
118
  "@rsbuild/core": {
@@ -12,7 +12,7 @@ import { createIdentifier } from './path-ids'
12
12
  import { getFrameworkOptions } from './framework-options'
13
13
  import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'
14
14
  import type { CodeSplitGroupings, SplitRouteIdentNodes } from '../constants'
15
- import type { Config } from '../config'
15
+ import type { Config, DeletableNodes } from '../config'
16
16
 
17
17
  type SplitNodeMeta = {
18
18
  routeIdent: SplitRouteIdentNodes
@@ -92,13 +92,24 @@ function removeSplitSearchParamFromFilename(filename: string) {
92
92
  return bareFilename!
93
93
  }
94
94
 
95
+ const splittableCreateRouteFns = ['createFileRoute']
96
+ const unsplittableCreateRouteFns = [
97
+ 'createRootRoute',
98
+ 'createRootRouteWithContext',
99
+ ]
100
+ const allCreateRouteFns = [
101
+ ...splittableCreateRouteFns,
102
+ ...unsplittableCreateRouteFns,
103
+ ]
104
+
95
105
  export function compileCodeSplitReferenceRoute(
96
106
  opts: ParseAstOptions & {
97
- runtimeEnv: 'dev' | 'prod'
98
107
  codeSplitGroupings: CodeSplitGroupings
108
+ deleteNodes?: Set<DeletableNodes>
99
109
  targetFramework: Config['target']
100
110
  filename: string
101
111
  id: string
112
+ addHmr?: boolean
102
113
  },
103
114
  ): GeneratorResult {
104
115
  const ast = parseAst(opts)
@@ -116,6 +127,8 @@ export function compileCodeSplitReferenceRoute(
116
127
  const LAZY_ROUTE_COMPONENT_IDENT = frameworkOptions.idents.lazyRouteComponent
117
128
  const LAZY_FN_IDENT = frameworkOptions.idents.lazyFn
118
129
 
130
+ let createRouteFn: string
131
+
119
132
  babel.traverse(ast, {
120
133
  Program: {
121
134
  enter(programPath) {
@@ -136,29 +149,48 @@ export function compileCodeSplitReferenceRoute(
136
149
  return
137
150
  }
138
151
 
139
- if (
140
- !(
141
- path.node.callee.name === 'createRoute' ||
142
- path.node.callee.name === 'createFileRoute'
143
- )
144
- ) {
152
+ if (!allCreateRouteFns.includes(path.node.callee.name)) {
145
153
  return
146
154
  }
147
155
 
156
+ createRouteFn = path.node.callee.name
157
+
148
158
  function babelHandleReference(routeOptions: t.Node | undefined) {
149
159
  const hasImportedOrDefinedIdentifier = (name: string) => {
150
160
  return programPath.scope.hasBinding(name)
151
161
  }
152
162
 
153
163
  if (t.isObjectExpression(routeOptions)) {
164
+ if (opts.deleteNodes && opts.deleteNodes.size > 0) {
165
+ routeOptions.properties = routeOptions.properties.filter(
166
+ (prop) => {
167
+ if (t.isObjectProperty(prop)) {
168
+ if (t.isIdentifier(prop.key)) {
169
+ if (opts.deleteNodes?.has(prop.key.name as any)) {
170
+ return false
171
+ }
172
+ }
173
+ }
174
+ return true
175
+ },
176
+ )
177
+ }
178
+ if (!splittableCreateRouteFns.includes(createRouteFn)) {
179
+ // we can't split this route but we still add HMR handling if enabled
180
+ if (opts.addHmr) {
181
+ programPath.pushContainer('body', routeHmrStatement)
182
+ }
183
+ // exit traversal so this route is not split
184
+ return programPath.stop()
185
+ }
154
186
  routeOptions.properties.forEach((prop) => {
155
187
  if (t.isObjectProperty(prop)) {
156
188
  if (t.isIdentifier(prop.key)) {
189
+ const key = prop.key.name
190
+
157
191
  // If the user has not specified a split grouping for this key
158
192
  // then we should not split it
159
- const codeSplitGroupingByKey = findIndexForSplitNode(
160
- prop.key.name,
161
- )
193
+ const codeSplitGroupingByKey = findIndexForSplitNode(key)
162
194
  if (codeSplitGroupingByKey === -1) {
163
195
  return
164
196
  }
@@ -168,7 +200,6 @@ export function compileCodeSplitReferenceRoute(
168
200
  ),
169
201
  ]
170
202
 
171
- const key = prop.key.name
172
203
  // find key in nodeSplitConfig
173
204
  const isNodeConfigAvailable = SPLIT_NODES_CONFIG.has(
174
205
  key as any,
@@ -249,19 +280,12 @@ export function compileCodeSplitReferenceRoute(
249
280
  ])
250
281
  }
251
282
 
252
- // If it's a component, we need to pass the function to check the Route.ssr value
253
- if (key === 'component') {
254
- prop.value = template.expression(
255
- `${LAZY_ROUTE_COMPONENT_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}', () => Route.ssr)`,
256
- )()
257
- } else {
258
- prop.value = template.expression(
259
- `${LAZY_ROUTE_COMPONENT_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`,
260
- )()
261
- }
283
+ prop.value = template.expression(
284
+ `${LAZY_ROUTE_COMPONENT_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`,
285
+ )()
262
286
 
263
287
  // add HMR handling
264
- if (opts.runtimeEnv !== 'prod') {
288
+ if (opts.addHmr) {
265
289
  programPath.pushContainer('body', routeHmrStatement)
266
290
  }
267
291
  }
@@ -416,12 +440,7 @@ export function compileCodeSplitVirtualRoute(
416
440
  return
417
441
  }
418
442
 
419
- if (
420
- !(
421
- path.node.callee.name === 'createRoute' ||
422
- path.node.callee.name === 'createFileRoute'
423
- )
424
- ) {
443
+ if (!splittableCreateRouteFns.includes(path.node.callee.name)) {
425
444
  return
426
445
  }
427
446
 
@@ -850,12 +869,10 @@ function resolveIdentifier(path: any, node: any): t.Node | undefined {
850
869
  return node
851
870
  }
852
871
 
853
- function removeIdentifierLiteral(path: any, node: any) {
854
- if (t.isIdentifier(node)) {
855
- const binding = path.scope.getBinding(node.name)
856
- if (binding) {
857
- binding.path.remove()
858
- }
872
+ function removeIdentifierLiteral(path: babel.NodePath, node: t.Identifier) {
873
+ const binding = path.scope.getBinding(node.name)
874
+ if (binding) {
875
+ binding.path.remove()
859
876
  }
860
877
  }
861
878
 
@@ -55,12 +55,28 @@ export type CodeSplittingOptions = {
55
55
  * @default [['component'],['pendingComponent'],['errorComponent'],['notFoundComponent']]
56
56
  */
57
57
  defaultBehavior?: CodeSplitGroupings
58
+
59
+ /**
60
+ * The nodes that shall be deleted from the route.
61
+ * @default undefined
62
+ */
63
+ deleteNodes?: Array<DeletableNodes>
64
+
65
+ /**
66
+ * @default true
67
+ */
68
+ addHmr?: boolean
58
69
  }
59
70
 
71
+ const DELETABLE_NODES = ['ssr'] as const
72
+ export const deletableNodesSchema = z.enum(DELETABLE_NODES)
60
73
  const codeSplittingOptionsSchema = z.object({
61
74
  splitBehavior: z.function().optional(),
62
75
  defaultBehavior: splitGroupingsSchema.optional(),
76
+ deleteNodes: z.array(deletableNodesSchema).optional(),
77
+ addHmr: z.boolean().optional().default(true),
63
78
  })
79
+ export type DeletableNodes = (typeof DELETABLE_NODES)[number]
64
80
 
65
81
  export const configSchema = generatorConfigSchema.extend({
66
82
  enableRouteGeneration: z.boolean().optional(),
@@ -69,6 +85,15 @@ export const configSchema = generatorConfigSchema.extend({
69
85
  return codeSplittingOptionsSchema.parse(v)
70
86
  })
71
87
  .optional(),
88
+ plugin: z
89
+ .object({
90
+ vite: z
91
+ .object({
92
+ environmentName: z.string().optional(),
93
+ })
94
+ .optional(),
95
+ })
96
+ .optional(),
72
97
  })
73
98
 
74
99
  export const getConfig = (inlineConfig: Partial<Config>, root: string) => {
@@ -120,11 +120,12 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
120
120
 
121
121
  const compiledReferenceRoute = compileCodeSplitReferenceRoute({
122
122
  code,
123
- runtimeEnv: isProduction ? 'prod' : 'dev',
124
123
  codeSplitGroupings: splitGroupings,
125
124
  targetFramework: userConfig.target,
126
125
  filename: id,
127
126
  id,
127
+ deleteNodes: new Set(userConfig.codeSplittingOptions?.deleteNodes),
128
+ addHmr: options.codeSplittingOptions?.addHmr && !isProduction,
128
129
  })
129
130
 
130
131
  if (debug) {
@@ -171,6 +172,11 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
171
172
  return result
172
173
  }
173
174
 
175
+ const includedCode = [
176
+ 'createFileRoute(',
177
+ 'createRootRoute(',
178
+ 'createRootRouteWithContext(',
179
+ ]
174
180
  return [
175
181
  {
176
182
  name: 'tanstack-router:code-splitter:compile-reference-file',
@@ -183,11 +189,16 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
183
189
  // this is necessary for webpack / rspack to avoid matching .html files
184
190
  include: /\.(m|c)?(j|t)sx?$/,
185
191
  },
186
- code: 'createFileRoute(',
192
+ code: {
193
+ include: includedCode,
194
+ },
187
195
  },
188
196
  handler(code, id) {
189
197
  const generatorFileInfo = globalThis.TSR_ROUTES_BY_ID_MAP?.get(id)
190
- if (generatorFileInfo && code.includes('createFileRoute(')) {
198
+ if (
199
+ generatorFileInfo &&
200
+ includedCode.some((included) => code.includes(included))
201
+ ) {
191
202
  for (const externalPlugin of bannedBeforeExternalPlugins) {
192
203
  if (!externalPlugin.frameworks.includes(framework)) {
193
204
  continue
@@ -210,6 +221,12 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory<
210
221
  ROOT = config.root
211
222
  userConfig = getConfig(options, ROOT)
212
223
  },
224
+ applyToEnvironment(environment) {
225
+ if (userConfig.plugin?.vite?.environmentName) {
226
+ return userConfig.plugin.vite.environmentName === environment.name
227
+ }
228
+ return true
229
+ },
213
230
  },
214
231
 
215
232
  rspack() {
@@ -73,14 +73,13 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory<
73
73
  configResolved() {
74
74
  initConfigAndGenerator()
75
75
  },
76
- async buildStart() {
77
- // to support vite 5, we need to optionally chain the access to the environment
78
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
79
- if (this.environment?.config?.consumer === 'server') {
80
- // When building in environment mode, we only need to generate routes
81
- // for the client environment
82
- return
76
+ applyToEnvironment(environment) {
77
+ if (userConfig.plugin?.vite?.environmentName) {
78
+ return userConfig.plugin.vite.environmentName === environment.name
83
79
  }
80
+ return true
81
+ },
82
+ async buildStart() {
84
83
  await generate()
85
84
  },
86
85
  sharedDuringBuild: true,
@@ -1,17 +1,27 @@
1
1
  import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'
2
2
  import { routeHmrStatement } from './route-hmr-statement'
3
3
  import { debug } from './utils'
4
- import type { Config } from './config'
4
+ import { getConfig } from './config'
5
5
  import type { UnpluginFactory } from 'unplugin'
6
+ import type { Config } from './config'
6
7
 
7
8
  /**
8
9
  * This plugin adds HMR support for file routes.
9
10
  * It is only added to the composed plugin in dev when autoCodeSplitting is disabled, since the code splitting plugin
10
11
  * handles HMR for code-split routes itself.
11
12
  */
13
+
14
+ const includeCode = [
15
+ 'createFileRoute(',
16
+ 'createRootRoute(',
17
+ 'createRootRouteWithContext(',
18
+ ]
12
19
  export const unpluginRouterHmrFactory: UnpluginFactory<
13
20
  Partial<Config> | undefined
14
- > = () => {
21
+ > = (options = {}) => {
22
+ let ROOT: string = process.cwd()
23
+ let userConfig = options as Config
24
+
15
25
  return {
16
26
  name: 'tanstack-router:hmr',
17
27
  enforce: 'pre',
@@ -19,7 +29,9 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
19
29
  filter: {
20
30
  // this is necessary for webpack / rspack to avoid matching .html files
21
31
  id: /\.(m|c)?(j|t)sx?$/,
22
- code: 'createFileRoute(',
32
+ code: {
33
+ include: includeCode,
34
+ },
23
35
  },
24
36
  handler(code, id) {
25
37
  if (!globalThis.TSR_ROUTES_BY_ID_MAP?.has(id)) {
@@ -42,5 +54,17 @@ export const unpluginRouterHmrFactory: UnpluginFactory<
42
54
  return result
43
55
  },
44
56
  },
57
+ vite: {
58
+ configResolved(config) {
59
+ ROOT = config.root
60
+ userConfig = getConfig(options, ROOT)
61
+ },
62
+ applyToEnvironment(environment) {
63
+ if (userConfig.plugin?.vite?.environmentName) {
64
+ return userConfig.plugin.vite.environmentName === environment.name
65
+ }
66
+ return true
67
+ },
68
+ },
45
69
  }
46
70
  }