@tanstack/router-plugin 1.168.21 → 1.168.23

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 (39) hide show
  1. package/dist/cjs/core/code-splitter/compilers.cjs +39 -32
  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/code-splitter/plugins/framework-plugins.cjs +10 -12
  5. package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs.map +1 -1
  6. package/dist/cjs/core/code-splitter/plugins/framework-plugins.d.cts +3 -4
  7. package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs +34 -16
  8. package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs.map +1 -1
  9. package/dist/cjs/core/code-splitter/plugins.d.cts +8 -1
  10. package/dist/cjs/core/config.cjs.map +1 -1
  11. package/dist/cjs/core/router-code-splitter-plugin.cjs +20 -11
  12. package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
  13. package/dist/cjs/core/router-hmr-plugin.cjs +1 -2
  14. package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
  15. package/dist/cjs/index.d.cts +1 -1
  16. package/dist/esm/core/code-splitter/compilers.d.ts +3 -2
  17. package/dist/esm/core/code-splitter/compilers.js +39 -32
  18. package/dist/esm/core/code-splitter/compilers.js.map +1 -1
  19. package/dist/esm/core/code-splitter/plugins/framework-plugins.d.ts +3 -4
  20. package/dist/esm/core/code-splitter/plugins/framework-plugins.js +10 -12
  21. package/dist/esm/core/code-splitter/plugins/framework-plugins.js.map +1 -1
  22. package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js +34 -16
  23. package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js.map +1 -1
  24. package/dist/esm/core/code-splitter/plugins.d.ts +8 -1
  25. package/dist/esm/core/config.js.map +1 -1
  26. package/dist/esm/core/router-code-splitter-plugin.js +21 -12
  27. package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
  28. package/dist/esm/core/router-hmr-plugin.js +2 -3
  29. package/dist/esm/core/router-hmr-plugin.js.map +1 -1
  30. package/dist/esm/index.d.ts +1 -1
  31. package/package.json +3 -3
  32. package/src/core/code-splitter/compilers.ts +12 -2
  33. package/src/core/code-splitter/plugins/framework-plugins.ts +11 -15
  34. package/src/core/code-splitter/plugins/react-refresh-route-components.ts +75 -25
  35. package/src/core/code-splitter/plugins.ts +12 -1
  36. package/src/core/config.ts +2 -2
  37. package/src/core/router-code-splitter-plugin.ts +31 -17
  38. package/src/core/router-hmr-plugin.ts +2 -3
  39. package/src/index.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../src/core/config.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n configSchema as generatorConfigSchema,\n getConfig as getGeneratorConfig,\n} from '@tanstack/router-generator'\nimport type {\n CreateFileRoute,\n RegisteredRouter,\n RouteIds,\n} from '@tanstack/router-core'\nimport type { CodeSplitGroupings } from './constants'\nimport type { ReferenceRouteCompilerPlugin } from './code-splitter/plugins'\n\nexport const splitGroupingsSchema = z\n .array(\n z.array(\n z.union([\n z.literal('loader'),\n z.literal('component'),\n z.literal('pendingComponent'),\n z.literal('errorComponent'),\n z.literal('notFoundComponent'),\n ]),\n ),\n {\n message:\n \" Must be an Array of Arrays containing the split groupings. i.e. [['component'], ['pendingComponent'], ['errorComponent', 'notFoundComponent']]\",\n },\n )\n .superRefine((val, ctx) => {\n const flattened = val.flat()\n const unique = [...new Set(flattened)]\n\n // Elements must be unique,\n // ie. this shouldn't be allows [['component'], ['component', 'loader']]\n if (unique.length !== flattened.length) {\n ctx.addIssue({\n code: 'custom',\n message:\n \" Split groupings must be unique and not repeated. i.e. i.e. [['component'], ['pendingComponent'], ['errorComponent', 'notFoundComponent']].\" +\n `\\n You input was: ${JSON.stringify(val)}.`,\n })\n }\n })\n\nexport type CodeSplittingOptions = {\n /**\n * Use this function to programmatically control the code splitting behavior\n * based on the `routeId` for each route.\n *\n * If you just need to change the default behavior, you can use the `defaultBehavior` option.\n * @param params\n */\n splitBehavior?: (params: {\n routeId: RouteIds<RegisteredRouter['routeTree']>\n }) => CodeSplitGroupings | undefined | void\n\n /**\n * The default/global configuration to control your code splitting behavior per route.\n * @default [['component'],['pendingComponent'],['errorComponent'],['notFoundComponent']]\n */\n defaultBehavior?: CodeSplitGroupings\n\n /**\n * The nodes that shall be deleted from the route.\n * @default undefined\n */\n deleteNodes?: Array<DeletableNodes>\n\n /**\n * @default true\n */\n addHmr?: boolean\n\n /**\n * Internal compiler plugins used by framework integrations.\n * @internal\n */\n compilerPlugins?: Array<ReferenceRouteCompilerPlugin>\n}\n\nexport type HmrStyle = 'vite' | 'webpack'\n\nexport type HmrOptions = {\n /**\n * Selects the HMR runtime style to emit code for.\n * - `'vite'` (default): ESM `import.meta.hot` with Vite accept-callback semantics.\n * - `'webpack'`: `import.meta.webpackHot` with webpack / Rspack `module.hot` re-execution semantics.\n *\n * Bundler-specific plugin entries (e.g. `rspack.ts`, `webpack.ts`) set this explicitly.\n */\n style?: HmrStyle\n}\n\nconst codeSplittingOptionsSchema = z.object({\n splitBehavior: z\n .custom<\n CodeSplittingOptions['splitBehavior']\n >((value) => typeof value === 'function')\n .optional(),\n defaultBehavior: splitGroupingsSchema.optional(),\n deleteNodes: z.array(z.string()).optional(),\n addHmr: z.boolean().optional().default(true),\n})\n\ntype FileRouteKeys = keyof (Parameters<\n CreateFileRoute<any, any, any, any, any>\n>[0] & {})\nexport type DeletableNodes = FileRouteKeys | (string & {})\n\nexport const configSchema = generatorConfigSchema.extend({\n enableRouteGeneration: z.boolean().optional(),\n codeSplittingOptions: z\n .custom<CodeSplittingOptions>((v) => {\n return codeSplittingOptionsSchema.parse(v)\n })\n .optional(),\n plugin: z\n .object({\n hmr: z\n .object({\n style: z.enum(['vite', 'webpack']).optional(),\n })\n .optional(),\n vite: z\n .object({\n environmentName: z.string().optional(),\n })\n .optional(),\n })\n .optional(),\n})\n\nexport const getConfig = (inlineConfig: Partial<Config>, root: string) => {\n const config = getGeneratorConfig(inlineConfig, root)\n\n return configSchema.parse({ ...inlineConfig, ...config })\n}\n\nexport type Config = z.infer<typeof configSchema>\nexport type ConfigInput = z.input<typeof configSchema>\nexport type ConfigOutput = z.output<typeof configSchema>\n"],"mappings":";;;AAaA,IAAa,uBAAuB,EACjC,MACC,EAAE,MACA,EAAE,MAAM;CACN,EAAE,QAAQ,QAAQ;CAClB,EAAE,QAAQ,WAAW;CACrB,EAAE,QAAQ,kBAAkB;CAC5B,EAAE,QAAQ,gBAAgB;CAC1B,EAAE,QAAQ,mBAAmB;AAC/B,CAAC,CACH,GACA,EACE,SACE,mJACJ,CACF,EACC,aAAa,KAAK,QAAQ;CACzB,MAAM,YAAY,IAAI,KAAK;CAK3B,IAAI,CAJY,GAAG,IAAI,IAAI,SAAS,CAIhC,EAAO,WAAW,UAAU,QAC9B,IAAI,SAAS;EACX,MAAM;EACN,SACE,kKACsB,KAAK,UAAU,GAAG,EAAE;CAC9C,CAAC;AAEL,CAAC;AAmDH,IAAM,6BAA6B,EAAE,OAAO;CAC1C,eAAe,EACZ,QAEE,UAAU,OAAO,UAAU,UAAU,EACvC,SAAS;CACZ,iBAAiB,qBAAqB,SAAS;CAC/C,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;CAC1C,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC7C,CAAC;AAOD,IAAa,iBAAe,aAAsB,OAAO;CACvD,uBAAuB,EAAE,QAAQ,EAAE,SAAS;CAC5C,sBAAsB,EACnB,QAA8B,MAAM;EACnC,OAAO,2BAA2B,MAAM,CAAC;CAC3C,CAAC,EACA,SAAS;CACZ,QAAQ,EACL,OAAO;EACN,KAAK,EACF,OAAO,EACN,OAAO,EAAE,KAAK,CAAC,QAAQ,SAAS,CAAC,EAAE,SAAS,EAC9C,CAAC,EACA,SAAS;EACZ,MAAM,EACH,OAAO,EACN,iBAAiB,EAAE,OAAO,EAAE,SAAS,EACvC,CAAC,EACA,SAAS;CACd,CAAC,EACA,SAAS;AACd,CAAC;AAED,IAAa,eAAa,cAA+B,SAAiB;CACxE,MAAM,SAAS,UAAmB,cAAc,IAAI;CAEpD,OAAO,eAAa,MAAM;EAAE,GAAG;EAAc,GAAG;CAAO,CAAC;AAC1D"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../src/core/config.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n configSchema as generatorConfigSchema,\n getConfig as getGeneratorConfig,\n} from '@tanstack/router-generator'\nimport type {\n CreateFileRoute,\n RegisteredRouter,\n RouteIds,\n} from '@tanstack/router-core'\nimport type { CodeSplitGroupings } from './constants'\nimport type { CodeSplitCompilerPlugin } from './code-splitter/plugins'\n\nexport const splitGroupingsSchema = z\n .array(\n z.array(\n z.union([\n z.literal('loader'),\n z.literal('component'),\n z.literal('pendingComponent'),\n z.literal('errorComponent'),\n z.literal('notFoundComponent'),\n ]),\n ),\n {\n message:\n \" Must be an Array of Arrays containing the split groupings. i.e. [['component'], ['pendingComponent'], ['errorComponent', 'notFoundComponent']]\",\n },\n )\n .superRefine((val, ctx) => {\n const flattened = val.flat()\n const unique = [...new Set(flattened)]\n\n // Elements must be unique,\n // ie. this shouldn't be allows [['component'], ['component', 'loader']]\n if (unique.length !== flattened.length) {\n ctx.addIssue({\n code: 'custom',\n message:\n \" Split groupings must be unique and not repeated. i.e. i.e. [['component'], ['pendingComponent'], ['errorComponent', 'notFoundComponent']].\" +\n `\\n You input was: ${JSON.stringify(val)}.`,\n })\n }\n })\n\nexport type CodeSplittingOptions = {\n /**\n * Use this function to programmatically control the code splitting behavior\n * based on the `routeId` for each route.\n *\n * If you just need to change the default behavior, you can use the `defaultBehavior` option.\n * @param params\n */\n splitBehavior?: (params: {\n routeId: RouteIds<RegisteredRouter['routeTree']>\n }) => CodeSplitGroupings | undefined | void\n\n /**\n * The default/global configuration to control your code splitting behavior per route.\n * @default [['component'],['pendingComponent'],['errorComponent'],['notFoundComponent']]\n */\n defaultBehavior?: CodeSplitGroupings\n\n /**\n * The nodes that shall be deleted from the route.\n * @default undefined\n */\n deleteNodes?: Array<DeletableNodes>\n\n /**\n * @default true\n */\n addHmr?: boolean\n\n /**\n * Internal compiler plugins used by framework integrations.\n * @internal\n */\n compilerPlugins?: Array<CodeSplitCompilerPlugin>\n}\n\nexport type HmrStyle = 'vite' | 'webpack'\n\nexport type HmrOptions = {\n /**\n * Selects the HMR runtime style to emit code for.\n * - `'vite'` (default): ESM `import.meta.hot` with Vite accept-callback semantics.\n * - `'webpack'`: `import.meta.webpackHot` with webpack / Rspack `module.hot` re-execution semantics.\n *\n * Bundler-specific plugin entries (e.g. `rspack.ts`, `webpack.ts`) set this explicitly.\n */\n style?: HmrStyle\n}\n\nconst codeSplittingOptionsSchema = z.object({\n splitBehavior: z\n .custom<\n CodeSplittingOptions['splitBehavior']\n >((value) => typeof value === 'function')\n .optional(),\n defaultBehavior: splitGroupingsSchema.optional(),\n deleteNodes: z.array(z.string()).optional(),\n addHmr: z.boolean().optional().default(true),\n})\n\ntype FileRouteKeys = keyof (Parameters<\n CreateFileRoute<any, any, any, any, any>\n>[0] & {})\nexport type DeletableNodes = FileRouteKeys | (string & {})\n\nexport const configSchema = generatorConfigSchema.extend({\n enableRouteGeneration: z.boolean().optional(),\n codeSplittingOptions: z\n .custom<CodeSplittingOptions>((v) => {\n return codeSplittingOptionsSchema.parse(v)\n })\n .optional(),\n plugin: z\n .object({\n hmr: z\n .object({\n style: z.enum(['vite', 'webpack']).optional(),\n })\n .optional(),\n vite: z\n .object({\n environmentName: z.string().optional(),\n })\n .optional(),\n })\n .optional(),\n})\n\nexport const getConfig = (inlineConfig: Partial<Config>, root: string) => {\n const config = getGeneratorConfig(inlineConfig, root)\n\n return configSchema.parse({ ...inlineConfig, ...config })\n}\n\nexport type Config = z.infer<typeof configSchema>\nexport type ConfigInput = z.input<typeof configSchema>\nexport type ConfigOutput = z.output<typeof configSchema>\n"],"mappings":";;;AAaA,IAAa,uBAAuB,EACjC,MACC,EAAE,MACA,EAAE,MAAM;CACN,EAAE,QAAQ,QAAQ;CAClB,EAAE,QAAQ,WAAW;CACrB,EAAE,QAAQ,kBAAkB;CAC5B,EAAE,QAAQ,gBAAgB;CAC1B,EAAE,QAAQ,mBAAmB;AAC/B,CAAC,CACH,GACA,EACE,SACE,mJACJ,CACF,EACC,aAAa,KAAK,QAAQ;CACzB,MAAM,YAAY,IAAI,KAAK;CAK3B,IAAI,CAJY,GAAG,IAAI,IAAI,SAAS,CAIhC,EAAO,WAAW,UAAU,QAC9B,IAAI,SAAS;EACX,MAAM;EACN,SACE,kKACsB,KAAK,UAAU,GAAG,EAAE;CAC9C,CAAC;AAEL,CAAC;AAmDH,IAAM,6BAA6B,EAAE,OAAO;CAC1C,eAAe,EACZ,QAEE,UAAU,OAAO,UAAU,UAAU,EACvC,SAAS;CACZ,iBAAiB,qBAAqB,SAAS;CAC/C,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;CAC1C,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC7C,CAAC;AAOD,IAAa,iBAAe,aAAsB,OAAO;CACvD,uBAAuB,EAAE,QAAQ,EAAE,SAAS;CAC5C,sBAAsB,EACnB,QAA8B,MAAM;EACnC,OAAO,2BAA2B,MAAM,CAAC;CAC3C,CAAC,EACA,SAAS;CACZ,QAAQ,EACL,OAAO;EACN,KAAK,EACF,OAAO,EACN,OAAO,EAAE,KAAK,CAAC,QAAQ,SAAS,CAAC,EAAE,SAAS,EAC9C,CAAC,EACA,SAAS;EACZ,MAAM,EACH,OAAO,EACN,iBAAiB,EAAE,OAAO,EAAE,SAAS,EACvC,CAAC,EACA,SAAS;CACd,CAAC,EACA,SAAS;AACd,CAAC;AAED,IAAa,eAAa,cAA+B,SAAiB;CACxE,MAAM,SAAS,UAAmB,cAAc,IAAI;CAEpD,OAAO,eAAa,MAAM;EAAE,GAAG;EAAc,GAAG;CAAO,CAAC;AAC1D"}
@@ -2,7 +2,7 @@ import { getConfig, splitGroupingsSchema } from "./config.js";
2
2
  import { defaultCodeSplitGroupings, splitRouteIdentNodes, tsrShared, tsrSplit } from "./constants.js";
3
3
  import { debug, normalizePath, routeFactoryCallCodeFilter } from "./utils.js";
4
4
  import { compileCodeSplitReferenceRoute, compileCodeSplitSharedRoute, compileCodeSplitVirtualRoute, computeSharedBindings, detectCodeSplitGroupingsFromRoute } from "./code-splitter/compilers.js";
5
- import { getReferenceRouteCompilerPlugins } from "./code-splitter/plugins/framework-plugins.js";
5
+ import { getFrameworkHmrCompilerPlugins } from "./code-splitter/plugins/framework-plugins.js";
6
6
  import { createRouterPluginContext } from "./router-plugin-context.js";
7
7
  import { fileURLToPath, pathToFileURL } from "node:url";
8
8
  import { decodeIdentifier, logDiff } from "@tanstack/router-utils";
@@ -43,11 +43,22 @@ var TRANSFORMATION_PLUGINS_BY_FRAMEWORK = {
43
43
  function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
44
44
  let ROOT = process.cwd();
45
45
  let userConfig;
46
+ let addHmr;
47
+ let hmrStyle;
48
+ let compilerPlugins;
49
+ let virtualRouteCompilerPlugins;
50
+ let isProduction = process.env.NODE_ENV === "production";
46
51
  function initUserConfig() {
47
52
  if (typeof options === "function") userConfig = options();
48
53
  else userConfig = getConfig(options, ROOT);
54
+ addHmr = (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction;
55
+ hmrStyle = userConfig.plugin?.hmr?.style ?? "vite";
56
+ compilerPlugins = [...addHmr ? getFrameworkHmrCompilerPlugins({
57
+ targetFramework: userConfig.target,
58
+ hmrStyle
59
+ }) ?? [] : [], ...userConfig.codeSplittingOptions?.compilerPlugins ?? []];
60
+ virtualRouteCompilerPlugins = compilerPlugins.filter((plugin) => plugin.onVirtualRouteSplitNode);
49
61
  }
50
- const isProduction = process.env.NODE_ENV === "production";
51
62
  const sharedBindingsMap = /* @__PURE__ */ new Map();
52
63
  const getGlobalCodeSplitGroupings = () => {
53
64
  return userConfig.codeSplittingOptions?.defaultBehavior || defaultCodeSplitGroupings;
@@ -84,8 +95,6 @@ function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
84
95
  });
85
96
  if (sharedBindings.size > 0) sharedBindingsMap.set(id, sharedBindings);
86
97
  else sharedBindingsMap.delete(id);
87
- const addHmr = (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction;
88
- const hmrStyle = userConfig.plugin?.hmr?.style ?? "vite";
89
98
  const compiledReferenceRoute = compileCodeSplitReferenceRoute({
90
99
  code,
91
100
  codeSplitGroupings: splitGroupings,
@@ -97,11 +106,7 @@ function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
97
106
  hmrStyle,
98
107
  hmrRouteId: generatorNodeInfo.routeId,
99
108
  sharedBindings: sharedBindings.size > 0 ? sharedBindings : void 0,
100
- compilerPlugins: [...getReferenceRouteCompilerPlugins({
101
- targetFramework: userConfig.target,
102
- addHmr,
103
- hmrStyle
104
- }) ?? [], ...userConfig.codeSplittingOptions?.compilerPlugins ?? []]
109
+ compilerPlugins
105
110
  });
106
111
  if (compiledReferenceRoute === null) {
107
112
  if (debug) console.info(`No changes made to route "${id}", skipping code-splitting.`);
@@ -125,7 +130,8 @@ function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
125
130
  code,
126
131
  filename: id,
127
132
  splitTargets: grouping,
128
- sharedBindings: sharedBindingsMap.get(baseId)
133
+ sharedBindings: sharedBindingsMap.get(baseId),
134
+ compilerPlugins: virtualRouteCompilerPlugins
129
135
  });
130
136
  if (debug) {
131
137
  logDiff(code, result.code);
@@ -154,6 +160,7 @@ function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
154
160
  },
155
161
  vite: {
156
162
  configResolved(config) {
163
+ isProduction = config.command === "build";
157
164
  ROOT = config.root;
158
165
  initUserConfig();
159
166
  const routerPluginIndex = config.plugins.findIndex((p) => p.name === CODE_SPLITTER_PLUGIN_NAME);
@@ -170,11 +177,13 @@ function createRouterCodeSplitterPlugin(options = {}, routerPluginContext) {
170
177
  return true;
171
178
  }
172
179
  },
173
- rspack() {
180
+ rspack(compiler) {
181
+ isProduction = compiler.options.mode === "production";
174
182
  ROOT = process.cwd();
175
183
  initUserConfig();
176
184
  },
177
- webpack() {
185
+ webpack(compiler) {
186
+ isProduction = compiler.options.mode === "production";
178
187
  ROOT = process.cwd();
179
188
  initUserConfig();
180
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"router-code-splitter-plugin.js","names":[],"sources":["../../../src/core/router-code-splitter-plugin.ts"],"sourcesContent":["/**\n * It is important to familiarize yourself with how the code-splitting works in this plugin.\n * https://github.com/TanStack/router/pull/3355\n */\n\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { decodeIdentifier, logDiff } from '@tanstack/router-utils'\nimport { getConfig, splitGroupingsSchema } from './config'\nimport {\n compileCodeSplitReferenceRoute,\n compileCodeSplitSharedRoute,\n compileCodeSplitVirtualRoute,\n computeSharedBindings,\n detectCodeSplitGroupingsFromRoute,\n} from './code-splitter/compilers'\nimport { getReferenceRouteCompilerPlugins } from './code-splitter/plugins/framework-plugins'\nimport {\n defaultCodeSplitGroupings,\n splitRouteIdentNodes,\n tsrShared,\n tsrSplit,\n} from './constants'\nimport { debug, normalizePath, routeFactoryCallCodeFilter } from './utils'\nimport { createRouterPluginContext } from './router-plugin-context'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\nimport type { GetRoutesByFileMapResultValue } from '@tanstack/router-generator'\nimport type { Config } from './config'\nimport type { RouterPluginContext } from './router-plugin-context'\nimport type {\n UnpluginFactory,\n TransformResult as UnpluginTransformResult,\n} from 'unplugin'\n\nconst CODE_SPLITTER_PLUGIN_NAME =\n 'tanstack-router:code-splitter:compile-reference-file'\n\ntype TransformationPluginInfo = {\n pluginNames: Array<string>\n pkg: string\n usage: string\n}\n\n/**\n * JSX transformation plugins grouped by framework.\n * These plugins must come AFTER the TanStack Router plugin in the Vite config.\n */\nconst TRANSFORMATION_PLUGINS_BY_FRAMEWORK: Record<\n string,\n Array<TransformationPluginInfo>\n> = {\n react: [\n {\n // Babel-based React plugin\n pluginNames: ['vite:react-babel', 'vite:react-refresh'],\n pkg: '@vitejs/plugin-react',\n usage: 'react()',\n },\n {\n // SWC-based React plugin\n pluginNames: ['vite:react-swc', 'vite:react-swc:resolve-runtime'],\n pkg: '@vitejs/plugin-react-swc',\n usage: 'reactSwc()',\n },\n {\n // OXC-based React plugin (deprecated but should still be handled)\n pluginNames: ['vite:react-oxc:config', 'vite:react-oxc:refresh-runtime'],\n pkg: '@vitejs/plugin-react-oxc',\n usage: 'reactOxc()',\n },\n ],\n solid: [\n {\n pluginNames: ['solid'],\n pkg: 'vite-plugin-solid',\n usage: 'solid()',\n },\n ],\n}\n\nexport function createRouterCodeSplitterPlugin(\n options: Partial<Config | (() => Config)> | undefined = {},\n routerPluginContext: RouterPluginContext,\n): ReturnType<UnpluginFactory<Partial<Config | (() => Config)> | undefined>> {\n let ROOT: string = process.cwd()\n let userConfig: Config\n\n function initUserConfig() {\n if (typeof options === 'function') {\n userConfig = options()\n } else {\n userConfig = getConfig(options, ROOT)\n }\n }\n const isProduction = process.env.NODE_ENV === 'production'\n // Map from normalized route file path → set of shared binding names.\n // Populated by the reference compiler, consumed by virtual and shared compilers.\n const sharedBindingsMap = new Map<string, Set<string>>()\n\n const getGlobalCodeSplitGroupings = () => {\n return (\n userConfig.codeSplittingOptions?.defaultBehavior ||\n defaultCodeSplitGroupings\n )\n }\n const getShouldSplitFn = () => {\n return userConfig.codeSplittingOptions?.splitBehavior\n }\n\n const handleCompilingReferenceFile = (\n code: string,\n id: string,\n generatorNodeInfo: GetRoutesByFileMapResultValue,\n ): UnpluginTransformResult => {\n if (debug) console.info('Compiling Route: ', id)\n\n const fromCode = detectCodeSplitGroupingsFromRoute({\n code,\n filename: id,\n })\n\n if (fromCode.groupings !== undefined) {\n const res = splitGroupingsSchema.safeParse(fromCode.groupings)\n if (!res.success) {\n const message = res.error.issues.map((e) => e.message).join('. ')\n throw new Error(\n `The groupings for the route \"${id}\" are invalid.\\n${message}`,\n )\n }\n }\n\n const userShouldSplitFn = getShouldSplitFn()\n\n const pluginSplitBehavior = userShouldSplitFn?.({\n routeId: generatorNodeInfo.routeId,\n }) as CodeSplitGroupings | undefined\n\n if (pluginSplitBehavior) {\n const res = splitGroupingsSchema.safeParse(pluginSplitBehavior)\n if (!res.success) {\n const message = res.error.issues.map((e) => e.message).join('. ')\n throw new Error(\n `The groupings returned when using \\`splitBehavior\\` for the route \"${id}\" are invalid.\\n${message}`,\n )\n }\n }\n\n const splitGroupings: CodeSplitGroupings =\n fromCode.groupings ?? pluginSplitBehavior ?? getGlobalCodeSplitGroupings()\n\n // Compute shared bindings before compiling the reference route\n const sharedBindings = computeSharedBindings({\n code,\n filename: id,\n codeSplitGroupings: splitGroupings,\n })\n if (sharedBindings.size > 0) {\n sharedBindingsMap.set(id, sharedBindings)\n } else {\n sharedBindingsMap.delete(id)\n }\n\n const addHmr =\n (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction\n const hmrStyle = userConfig.plugin?.hmr?.style ?? 'vite'\n\n const compiledReferenceRoute = compileCodeSplitReferenceRoute({\n code,\n codeSplitGroupings: splitGroupings,\n targetFramework: userConfig.target,\n filename: id,\n id,\n deleteNodes: userConfig.codeSplittingOptions?.deleteNodes\n ? new Set(userConfig.codeSplittingOptions.deleteNodes)\n : undefined,\n addHmr,\n hmrStyle,\n hmrRouteId: generatorNodeInfo.routeId,\n sharedBindings: sharedBindings.size > 0 ? sharedBindings : undefined,\n compilerPlugins: [\n ...(getReferenceRouteCompilerPlugins({\n targetFramework: userConfig.target,\n addHmr,\n hmrStyle,\n }) ?? []),\n ...(userConfig.codeSplittingOptions?.compilerPlugins ?? []),\n ],\n })\n\n if (compiledReferenceRoute === null) {\n if (debug) {\n console.info(\n `No changes made to route \"${id}\", skipping code-splitting.`,\n )\n }\n return null\n }\n if (debug) {\n logDiff(code, compiledReferenceRoute.code)\n console.log('Output:\\n', compiledReferenceRoute.code + '\\n\\n')\n }\n\n return compiledReferenceRoute\n }\n\n const handleCompilingVirtualFile = (\n code: string,\n id: string,\n ): UnpluginTransformResult => {\n if (debug) console.info('Splitting Route: ', id)\n\n const [_, ...pathnameParts] = id.split('?')\n\n const searchParams = new URLSearchParams(pathnameParts.join('?'))\n const splitValue = searchParams.get(tsrSplit)\n\n if (!splitValue) {\n throw new Error(\n `The split value for the virtual route \"${id}\" was not found.`,\n )\n }\n\n const rawGrouping = decodeIdentifier(splitValue)\n const grouping = [...new Set(rawGrouping)].filter((p) =>\n splitRouteIdentNodes.includes(p as any),\n ) as Array<SplitRouteIdentNodes>\n\n const baseId = id.split('?')[0]!\n const resolvedSharedBindings = sharedBindingsMap.get(baseId)\n\n const result = compileCodeSplitVirtualRoute({\n code,\n filename: id,\n splitTargets: grouping,\n sharedBindings: resolvedSharedBindings,\n })\n\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n\n return result\n }\n\n return [\n {\n name: 'tanstack-router:code-splitter:compile-reference-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: {\n exclude: [tsrSplit, tsrShared],\n // this is necessary for webpack / rspack to avoid matching .html files\n include: /\\.(m|c)?(j|t)sx?$/,\n },\n code: {\n include: routeFactoryCallCodeFilter,\n },\n },\n handler(code, id) {\n const normalizedId = normalizePath(id)\n const generatorFileInfo =\n routerPluginContext.routesByFile.get(normalizedId)\n if (generatorFileInfo) {\n return handleCompilingReferenceFile(\n code,\n normalizedId,\n generatorFileInfo,\n )\n }\n\n return null\n },\n },\n\n vite: {\n configResolved(config) {\n ROOT = config.root\n initUserConfig()\n\n // Validate plugin order - router must come before JSX transformation plugins\n const routerPluginIndex = config.plugins.findIndex(\n (p) => p.name === CODE_SPLITTER_PLUGIN_NAME,\n )\n\n if (routerPluginIndex === -1) return\n\n const frameworkPlugins =\n TRANSFORMATION_PLUGINS_BY_FRAMEWORK[userConfig.target]\n if (!frameworkPlugins) return\n\n for (const transformPlugin of frameworkPlugins) {\n const transformPluginIndex = config.plugins.findIndex((p) =>\n transformPlugin.pluginNames.includes(p.name),\n )\n\n if (\n transformPluginIndex !== -1 &&\n transformPluginIndex < routerPluginIndex\n ) {\n throw new Error(\n `Plugin order error: '${transformPlugin.pkg}' is placed before '@tanstack/router-plugin'.\\n\\n` +\n `The TanStack Router plugin must come BEFORE JSX transformation plugins.\\n\\n` +\n `Please update your Vite config:\\n\\n` +\n ` plugins: [\\n` +\n ` tanstackRouter(),\\n` +\n ` ${transformPlugin.usage},\\n` +\n ` ]\\n`,\n )\n }\n }\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 rspack() {\n ROOT = process.cwd()\n initUserConfig()\n },\n\n webpack() {\n ROOT = process.cwd()\n initUserConfig()\n },\n },\n {\n name: 'tanstack-router:code-splitter:compile-virtual-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: /tsr-split/,\n },\n handler(code, id) {\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n const normalizedId = normalizePath(fileURLToPath(url))\n return handleCompilingVirtualFile(code, normalizedId)\n },\n },\n\n vite: {\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 name: 'tanstack-router:code-splitter:compile-shared-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: /tsr-shared/,\n },\n handler(code, id) {\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n const normalizedId = normalizePath(fileURLToPath(url))\n const [baseId] = normalizedId.split('?')\n\n if (!baseId) return null\n\n const sharedBindings = sharedBindingsMap.get(baseId)\n if (!sharedBindings || sharedBindings.size === 0) return null\n\n if (debug) console.info('Compiling Shared Module: ', id)\n\n const result = compileCodeSplitSharedRoute({\n code,\n sharedBindings,\n filename: normalizedId,\n })\n\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n\n return result\n },\n },\n\n vite: {\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}\n\nexport const unpluginRouterCodeSplitterFactory: UnpluginFactory<\n Partial<Config | (() => Config)> | undefined\n> = (options = {}) => {\n return createRouterCodeSplitterPlugin(options, createRouterPluginContext())\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"router-code-splitter-plugin.js","names":[],"sources":["../../../src/core/router-code-splitter-plugin.ts"],"sourcesContent":["/**\n * It is important to familiarize yourself with how the code-splitting works in this plugin.\n * https://github.com/TanStack/router/pull/3355\n */\n\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { decodeIdentifier, logDiff } from '@tanstack/router-utils'\nimport { getConfig, splitGroupingsSchema } from './config'\nimport {\n compileCodeSplitReferenceRoute,\n compileCodeSplitSharedRoute,\n compileCodeSplitVirtualRoute,\n computeSharedBindings,\n detectCodeSplitGroupingsFromRoute,\n} from './code-splitter/compilers'\nimport { getFrameworkHmrCompilerPlugins } from './code-splitter/plugins/framework-plugins'\nimport {\n defaultCodeSplitGroupings,\n splitRouteIdentNodes,\n tsrShared,\n tsrSplit,\n} from './constants'\nimport { debug, normalizePath, routeFactoryCallCodeFilter } from './utils'\nimport { createRouterPluginContext } from './router-plugin-context'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\nimport type { GetRoutesByFileMapResultValue } from '@tanstack/router-generator'\nimport type { CodeSplitCompilerPlugin } from './code-splitter/plugins'\nimport type { Config, HmrStyle } from './config'\nimport type { RouterPluginContext } from './router-plugin-context'\nimport type {\n UnpluginFactory,\n TransformResult as UnpluginTransformResult,\n} from 'unplugin'\n\nconst CODE_SPLITTER_PLUGIN_NAME =\n 'tanstack-router:code-splitter:compile-reference-file'\n\ntype TransformationPluginInfo = {\n pluginNames: Array<string>\n pkg: string\n usage: string\n}\n\n/**\n * JSX transformation plugins grouped by framework.\n * These plugins must come AFTER the TanStack Router plugin in the Vite config.\n */\nconst TRANSFORMATION_PLUGINS_BY_FRAMEWORK: Record<\n string,\n Array<TransformationPluginInfo>\n> = {\n react: [\n {\n // Babel-based React plugin\n pluginNames: ['vite:react-babel', 'vite:react-refresh'],\n pkg: '@vitejs/plugin-react',\n usage: 'react()',\n },\n {\n // SWC-based React plugin\n pluginNames: ['vite:react-swc', 'vite:react-swc:resolve-runtime'],\n pkg: '@vitejs/plugin-react-swc',\n usage: 'reactSwc()',\n },\n {\n // OXC-based React plugin (deprecated but should still be handled)\n pluginNames: ['vite:react-oxc:config', 'vite:react-oxc:refresh-runtime'],\n pkg: '@vitejs/plugin-react-oxc',\n usage: 'reactOxc()',\n },\n ],\n solid: [\n {\n pluginNames: ['solid'],\n pkg: 'vite-plugin-solid',\n usage: 'solid()',\n },\n ],\n}\n\nexport function createRouterCodeSplitterPlugin(\n options: Partial<Config | (() => Config)> | undefined = {},\n routerPluginContext: RouterPluginContext,\n): ReturnType<UnpluginFactory<Partial<Config | (() => Config)> | undefined>> {\n let ROOT: string = process.cwd()\n let userConfig: Config\n let addHmr: boolean\n let hmrStyle: HmrStyle\n let compilerPlugins: Array<CodeSplitCompilerPlugin>\n let virtualRouteCompilerPlugins: Array<CodeSplitCompilerPlugin>\n\n let isProduction = process.env.NODE_ENV === 'production'\n\n function initUserConfig() {\n if (typeof options === 'function') {\n userConfig = options()\n } else {\n userConfig = getConfig(options, ROOT)\n }\n\n addHmr = (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction\n hmrStyle = userConfig.plugin?.hmr?.style ?? 'vite'\n compilerPlugins = [\n ...(addHmr\n ? (getFrameworkHmrCompilerPlugins({\n targetFramework: userConfig.target,\n hmrStyle,\n }) ?? [])\n : []),\n ...(userConfig.codeSplittingOptions?.compilerPlugins ?? []),\n ]\n virtualRouteCompilerPlugins = compilerPlugins.filter(\n (plugin) => plugin.onVirtualRouteSplitNode,\n )\n }\n // Map from normalized route file path → set of shared binding names.\n // Populated by the reference compiler, consumed by virtual and shared compilers.\n const sharedBindingsMap = new Map<string, Set<string>>()\n\n const getGlobalCodeSplitGroupings = () => {\n return (\n userConfig.codeSplittingOptions?.defaultBehavior ||\n defaultCodeSplitGroupings\n )\n }\n const getShouldSplitFn = () => {\n return userConfig.codeSplittingOptions?.splitBehavior\n }\n\n const handleCompilingReferenceFile = (\n code: string,\n id: string,\n generatorNodeInfo: GetRoutesByFileMapResultValue,\n ): UnpluginTransformResult => {\n if (debug) console.info('Compiling Route: ', id)\n\n const fromCode = detectCodeSplitGroupingsFromRoute({\n code,\n filename: id,\n })\n\n if (fromCode.groupings !== undefined) {\n const res = splitGroupingsSchema.safeParse(fromCode.groupings)\n if (!res.success) {\n const message = res.error.issues.map((e) => e.message).join('. ')\n throw new Error(\n `The groupings for the route \"${id}\" are invalid.\\n${message}`,\n )\n }\n }\n\n const userShouldSplitFn = getShouldSplitFn()\n\n const pluginSplitBehavior = userShouldSplitFn?.({\n routeId: generatorNodeInfo.routeId,\n }) as CodeSplitGroupings | undefined\n\n if (pluginSplitBehavior) {\n const res = splitGroupingsSchema.safeParse(pluginSplitBehavior)\n if (!res.success) {\n const message = res.error.issues.map((e) => e.message).join('. ')\n throw new Error(\n `The groupings returned when using \\`splitBehavior\\` for the route \"${id}\" are invalid.\\n${message}`,\n )\n }\n }\n\n const splitGroupings: CodeSplitGroupings =\n fromCode.groupings ?? pluginSplitBehavior ?? getGlobalCodeSplitGroupings()\n\n // Compute shared bindings before compiling the reference route\n const sharedBindings = computeSharedBindings({\n code,\n filename: id,\n codeSplitGroupings: splitGroupings,\n })\n if (sharedBindings.size > 0) {\n sharedBindingsMap.set(id, sharedBindings)\n } else {\n sharedBindingsMap.delete(id)\n }\n\n const compiledReferenceRoute = compileCodeSplitReferenceRoute({\n code,\n codeSplitGroupings: splitGroupings,\n targetFramework: userConfig.target,\n filename: id,\n id,\n deleteNodes: userConfig.codeSplittingOptions?.deleteNodes\n ? new Set(userConfig.codeSplittingOptions.deleteNodes)\n : undefined,\n addHmr,\n hmrStyle,\n hmrRouteId: generatorNodeInfo.routeId,\n sharedBindings: sharedBindings.size > 0 ? sharedBindings : undefined,\n compilerPlugins,\n })\n\n if (compiledReferenceRoute === null) {\n if (debug) {\n console.info(\n `No changes made to route \"${id}\", skipping code-splitting.`,\n )\n }\n return null\n }\n if (debug) {\n logDiff(code, compiledReferenceRoute.code)\n console.log('Output:\\n', compiledReferenceRoute.code + '\\n\\n')\n }\n\n return compiledReferenceRoute\n }\n\n const handleCompilingVirtualFile = (\n code: string,\n id: string,\n ): UnpluginTransformResult => {\n if (debug) console.info('Splitting Route: ', id)\n\n const [_, ...pathnameParts] = id.split('?')\n\n const searchParams = new URLSearchParams(pathnameParts.join('?'))\n const splitValue = searchParams.get(tsrSplit)\n\n if (!splitValue) {\n throw new Error(\n `The split value for the virtual route \"${id}\" was not found.`,\n )\n }\n\n const rawGrouping = decodeIdentifier(splitValue)\n const grouping = [...new Set(rawGrouping)].filter((p) =>\n splitRouteIdentNodes.includes(p as any),\n ) as Array<SplitRouteIdentNodes>\n\n const baseId = id.split('?')[0]!\n const resolvedSharedBindings = sharedBindingsMap.get(baseId)\n\n const result = compileCodeSplitVirtualRoute({\n code,\n filename: id,\n splitTargets: grouping,\n sharedBindings: resolvedSharedBindings,\n compilerPlugins: virtualRouteCompilerPlugins,\n })\n\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n\n return result\n }\n\n return [\n {\n name: 'tanstack-router:code-splitter:compile-reference-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: {\n exclude: [tsrSplit, tsrShared],\n // this is necessary for webpack / rspack to avoid matching .html files\n include: /\\.(m|c)?(j|t)sx?$/,\n },\n code: {\n include: routeFactoryCallCodeFilter,\n },\n },\n handler(code, id) {\n const normalizedId = normalizePath(id)\n const generatorFileInfo =\n routerPluginContext.routesByFile.get(normalizedId)\n if (generatorFileInfo) {\n return handleCompilingReferenceFile(\n code,\n normalizedId,\n generatorFileInfo,\n )\n }\n\n return null\n },\n },\n\n vite: {\n configResolved(config) {\n isProduction = config.command === 'build'\n ROOT = config.root\n initUserConfig()\n\n // Validate plugin order - router must come before JSX transformation plugins\n const routerPluginIndex = config.plugins.findIndex(\n (p) => p.name === CODE_SPLITTER_PLUGIN_NAME,\n )\n\n if (routerPluginIndex === -1) return\n\n const frameworkPlugins =\n TRANSFORMATION_PLUGINS_BY_FRAMEWORK[userConfig.target]\n if (!frameworkPlugins) return\n\n for (const transformPlugin of frameworkPlugins) {\n const transformPluginIndex = config.plugins.findIndex((p) =>\n transformPlugin.pluginNames.includes(p.name),\n )\n\n if (\n transformPluginIndex !== -1 &&\n transformPluginIndex < routerPluginIndex\n ) {\n throw new Error(\n `Plugin order error: '${transformPlugin.pkg}' is placed before '@tanstack/router-plugin'.\\n\\n` +\n `The TanStack Router plugin must come BEFORE JSX transformation plugins.\\n\\n` +\n `Please update your Vite config:\\n\\n` +\n ` plugins: [\\n` +\n ` tanstackRouter(),\\n` +\n ` ${transformPlugin.usage},\\n` +\n ` ]\\n`,\n )\n }\n }\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 rspack(compiler) {\n isProduction = compiler.options.mode === 'production'\n ROOT = process.cwd()\n initUserConfig()\n },\n\n webpack(compiler) {\n isProduction = compiler.options.mode === 'production'\n ROOT = process.cwd()\n initUserConfig()\n },\n },\n {\n name: 'tanstack-router:code-splitter:compile-virtual-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: /tsr-split/,\n },\n handler(code, id) {\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n const normalizedId = normalizePath(fileURLToPath(url))\n return handleCompilingVirtualFile(code, normalizedId)\n },\n },\n\n vite: {\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 name: 'tanstack-router:code-splitter:compile-shared-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: /tsr-shared/,\n },\n handler(code, id) {\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n const normalizedId = normalizePath(fileURLToPath(url))\n const [baseId] = normalizedId.split('?')\n\n if (!baseId) return null\n\n const sharedBindings = sharedBindingsMap.get(baseId)\n if (!sharedBindings || sharedBindings.size === 0) return null\n\n if (debug) console.info('Compiling Shared Module: ', id)\n\n const result = compileCodeSplitSharedRoute({\n code,\n sharedBindings,\n filename: normalizedId,\n })\n\n if (debug) {\n logDiff(code, result.code)\n console.log('Output:\\n', result.code + '\\n\\n')\n }\n\n return result\n },\n },\n\n vite: {\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}\n\nexport const unpluginRouterCodeSplitterFactory: UnpluginFactory<\n Partial<Config | (() => Config)> | undefined\n> = (options = {}) => {\n return createRouterCodeSplitterPlugin(options, createRouterPluginContext())\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { getConfig } from "./config.js";
2
2
  import { createRouteHmrStatement } from "./hmr/select-adapter.js";
3
3
  import { debug, normalizePath, routeFactoryCallCodeFilter } from "./utils.js";
4
4
  import { compileCodeSplitReferenceRoute } from "./code-splitter/compilers.js";
5
- import { getReferenceRouteCompilerPlugins } from "./code-splitter/plugins/framework-plugins.js";
5
+ import { getFrameworkHmrCompilerPlugins } from "./code-splitter/plugins/framework-plugins.js";
6
6
  import { generateFromAst, logDiff, parseAst } from "@tanstack/router-utils";
7
7
  //#region src/core/router-hmr-plugin.ts
8
8
  /**
@@ -31,9 +31,8 @@ function createRouterHmrPlugin(options = {}, routerPluginContext) {
31
31
  if (debug) console.info("Adding HMR handling to route ", normalizedId);
32
32
  const hmrStyle = userConfig.plugin?.hmr?.style ?? "vite";
33
33
  if (userConfig.target === "react") {
34
- const compilerPlugins = getReferenceRouteCompilerPlugins({
34
+ const compilerPlugins = getFrameworkHmrCompilerPlugins({
35
35
  targetFramework: "react",
36
- addHmr: true,
37
36
  hmrStyle
38
37
  });
39
38
  const compiled = compileCodeSplitReferenceRoute({
@@ -1 +1 @@
1
- {"version":3,"file":"router-hmr-plugin.js","names":[],"sources":["../../../src/core/router-hmr-plugin.ts"],"sourcesContent":["import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'\nimport { compileCodeSplitReferenceRoute } from './code-splitter/compilers'\nimport { getReferenceRouteCompilerPlugins } from './code-splitter/plugins/framework-plugins'\nimport { createRouteHmrStatement } from './hmr'\nimport { debug, normalizePath, routeFactoryCallCodeFilter } from './utils'\nimport { getConfig } from './config'\nimport { createRouterPluginContext } from './router-plugin-context'\nimport type { UnpluginFactory } from 'unplugin'\nimport type { Config } from './config'\nimport type { RouterPluginContext } from './router-plugin-context'\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\nexport function createRouterHmrPlugin(\n options: Partial<Config | (() => Config)> | undefined = {},\n routerPluginContext: RouterPluginContext,\n): ReturnType<UnpluginFactory<Partial<Config> | undefined>> {\n let ROOT: string = process.cwd()\n\n const resolveUserConfig = () => {\n return getConfig(typeof options === 'function' ? options() : options, ROOT)\n }\n\n let userConfig = resolveUserConfig()\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: routeFactoryCallCodeFilter,\n },\n },\n handler(code, id) {\n const normalizedId = normalizePath(id)\n const routeEntry = routerPluginContext.routesByFile.get(normalizedId)\n if (!routeEntry) {\n return null\n }\n\n if (debug) console.info('Adding HMR handling to route ', normalizedId)\n\n const hmrStyle = userConfig.plugin?.hmr?.style ?? 'vite'\n\n if (userConfig.target === 'react') {\n const compilerPlugins = getReferenceRouteCompilerPlugins({\n targetFramework: 'react',\n addHmr: true,\n hmrStyle,\n })\n const compiled = compileCodeSplitReferenceRoute({\n code,\n filename: normalizedId,\n id: normalizedId,\n addHmr: true,\n hmrStyle,\n hmrRouteId: routeEntry.routeId,\n codeSplitGroupings: [],\n targetFramework: 'react',\n compilerPlugins,\n })\n\n if (compiled) {\n if (debug) {\n logDiff(code, compiled.code)\n console.log('Output:\\n', compiled.code + '\\n\\n')\n }\n\n return compiled\n }\n }\n\n const ast = parseAst({ code, filename: normalizedId })\n ast.program.body.push(\n ...createRouteHmrStatement([], {\n hmrStyle,\n targetFramework: userConfig.target,\n routeId: routeEntry.routeId,\n }),\n )\n const result = generateFromAst(ast, {\n sourceMaps: true,\n filename: normalizedId,\n sourceFileName: normalizedId,\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 = resolveUserConfig()\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\nexport const unpluginRouterHmrFactory: UnpluginFactory<\n Partial<Config> | undefined\n> = (options = {}) => {\n return createRouterHmrPlugin(options, createRouterPluginContext())\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,SAAgB,sBACd,UAAwD,CAAC,GACzD,qBAC0D;CAC1D,IAAI,OAAe,QAAQ,IAAI;CAE/B,MAAM,0BAA0B;EAC9B,OAAO,UAAU,OAAO,YAAY,aAAa,QAAQ,IAAI,SAAS,IAAI;CAC5E;CAEA,IAAI,aAAa,kBAAkB;CAEnC,OAAO;EACL,MAAM;EACN,SAAS;EACT,WAAW;GACT,QAAQ;IAEN,IAAI;IACJ,MAAM,EACJ,SAAS,2BACX;GACF;GACA,QAAQ,MAAM,IAAI;IAChB,MAAM,eAAe,cAAc,EAAE;IACrC,MAAM,aAAa,oBAAoB,aAAa,IAAI,YAAY;IACpE,IAAI,CAAC,YACH,OAAO;IAGT,IAAI,OAAO,QAAQ,KAAK,iCAAiC,YAAY;IAErE,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;IAElD,IAAI,WAAW,WAAW,SAAS;KACjC,MAAM,kBAAkB,iCAAiC;MACvD,iBAAiB;MACjB,QAAQ;MACR;KACF,CAAC;KACD,MAAM,WAAW,+BAA+B;MAC9C;MACA,UAAU;MACV,IAAI;MACJ,QAAQ;MACR;MACA,YAAY,WAAW;MACvB,oBAAoB,CAAC;MACrB,iBAAiB;MACjB;KACF,CAAC;KAED,IAAI,UAAU;MACZ,IAAI,OAAO;OACT,QAAQ,MAAM,SAAS,IAAI;OAC3B,QAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;MACjD;MAEA,OAAO;KACT;IACF;IAEA,MAAM,MAAM,SAAS;KAAE;KAAM,UAAU;IAAa,CAAC;IACrD,IAAI,QAAQ,KAAK,KACf,GAAG,wBAAwB,CAAC,GAAG;KAC7B;KACA,iBAAiB,WAAW;KAC5B,SAAS,WAAW;IACtB,CAAC,CACH;IACA,MAAM,SAAS,gBAAgB,KAAK;KAClC,YAAY;KACZ,UAAU;KACV,gBAAgB;IAClB,CAAC;IACD,IAAI,OAAO;KACT,QAAQ,MAAM,OAAO,IAAI;KACzB,QAAQ,IAAI,aAAa,OAAO,OAAO,MAAM;IAC/C;IACA,OAAO;GACT;EACF;EACA,MAAM;GACJ,eAAe,QAAQ;IACrB,OAAO,OAAO;IACd,aAAa,kBAAkB;GACjC;GACA,mBAAmB,aAAa;IAC9B,IAAI,WAAW,QAAQ,MAAM,iBAC3B,OAAO,WAAW,OAAO,KAAK,oBAAoB,YAAY;IAEhE,OAAO;GACT;EACF;CACF;AACF"}
1
+ {"version":3,"file":"router-hmr-plugin.js","names":[],"sources":["../../../src/core/router-hmr-plugin.ts"],"sourcesContent":["import { generateFromAst, logDiff, parseAst } from '@tanstack/router-utils'\nimport { compileCodeSplitReferenceRoute } from './code-splitter/compilers'\nimport { getFrameworkHmrCompilerPlugins } from './code-splitter/plugins/framework-plugins'\nimport { createRouteHmrStatement } from './hmr'\nimport { debug, normalizePath, routeFactoryCallCodeFilter } from './utils'\nimport { getConfig } from './config'\nimport { createRouterPluginContext } from './router-plugin-context'\nimport type { UnpluginFactory } from 'unplugin'\nimport type { Config } from './config'\nimport type { RouterPluginContext } from './router-plugin-context'\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\nexport function createRouterHmrPlugin(\n options: Partial<Config | (() => Config)> | undefined = {},\n routerPluginContext: RouterPluginContext,\n): ReturnType<UnpluginFactory<Partial<Config> | undefined>> {\n let ROOT: string = process.cwd()\n\n const resolveUserConfig = () => {\n return getConfig(typeof options === 'function' ? options() : options, ROOT)\n }\n\n let userConfig = resolveUserConfig()\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: routeFactoryCallCodeFilter,\n },\n },\n handler(code, id) {\n const normalizedId = normalizePath(id)\n const routeEntry = routerPluginContext.routesByFile.get(normalizedId)\n if (!routeEntry) {\n return null\n }\n\n if (debug) console.info('Adding HMR handling to route ', normalizedId)\n\n const hmrStyle = userConfig.plugin?.hmr?.style ?? 'vite'\n\n if (userConfig.target === 'react') {\n const compilerPlugins = getFrameworkHmrCompilerPlugins({\n targetFramework: 'react',\n hmrStyle,\n })\n const compiled = compileCodeSplitReferenceRoute({\n code,\n filename: normalizedId,\n id: normalizedId,\n addHmr: true,\n hmrStyle,\n hmrRouteId: routeEntry.routeId,\n codeSplitGroupings: [],\n targetFramework: 'react',\n compilerPlugins,\n })\n\n if (compiled) {\n if (debug) {\n logDiff(code, compiled.code)\n console.log('Output:\\n', compiled.code + '\\n\\n')\n }\n\n return compiled\n }\n }\n\n const ast = parseAst({ code, filename: normalizedId })\n ast.program.body.push(\n ...createRouteHmrStatement([], {\n hmrStyle,\n targetFramework: userConfig.target,\n routeId: routeEntry.routeId,\n }),\n )\n const result = generateFromAst(ast, {\n sourceMaps: true,\n filename: normalizedId,\n sourceFileName: normalizedId,\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 = resolveUserConfig()\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\nexport const unpluginRouterHmrFactory: UnpluginFactory<\n Partial<Config> | undefined\n> = (options = {}) => {\n return createRouterHmrPlugin(options, createRouterPluginContext())\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,SAAgB,sBACd,UAAwD,CAAC,GACzD,qBAC0D;CAC1D,IAAI,OAAe,QAAQ,IAAI;CAE/B,MAAM,0BAA0B;EAC9B,OAAO,UAAU,OAAO,YAAY,aAAa,QAAQ,IAAI,SAAS,IAAI;CAC5E;CAEA,IAAI,aAAa,kBAAkB;CAEnC,OAAO;EACL,MAAM;EACN,SAAS;EACT,WAAW;GACT,QAAQ;IAEN,IAAI;IACJ,MAAM,EACJ,SAAS,2BACX;GACF;GACA,QAAQ,MAAM,IAAI;IAChB,MAAM,eAAe,cAAc,EAAE;IACrC,MAAM,aAAa,oBAAoB,aAAa,IAAI,YAAY;IACpE,IAAI,CAAC,YACH,OAAO;IAGT,IAAI,OAAO,QAAQ,KAAK,iCAAiC,YAAY;IAErE,MAAM,WAAW,WAAW,QAAQ,KAAK,SAAS;IAElD,IAAI,WAAW,WAAW,SAAS;KACjC,MAAM,kBAAkB,+BAA+B;MACrD,iBAAiB;MACjB;KACF,CAAC;KACD,MAAM,WAAW,+BAA+B;MAC9C;MACA,UAAU;MACV,IAAI;MACJ,QAAQ;MACR;MACA,YAAY,WAAW;MACvB,oBAAoB,CAAC;MACrB,iBAAiB;MACjB;KACF,CAAC;KAED,IAAI,UAAU;MACZ,IAAI,OAAO;OACT,QAAQ,MAAM,SAAS,IAAI;OAC3B,QAAQ,IAAI,aAAa,SAAS,OAAO,MAAM;MACjD;MAEA,OAAO;KACT;IACF;IAEA,MAAM,MAAM,SAAS;KAAE;KAAM,UAAU;IAAa,CAAC;IACrD,IAAI,QAAQ,KAAK,KACf,GAAG,wBAAwB,CAAC,GAAG;KAC7B;KACA,iBAAiB,WAAW;KAC5B,SAAS,WAAW;IACtB,CAAC,CACH;IACA,MAAM,SAAS,gBAAgB,KAAK;KAClC,YAAY;KACZ,UAAU;KACV,gBAAgB;IAClB,CAAC;IACD,IAAI,OAAO;KACT,QAAQ,MAAM,OAAO,IAAI;KACzB,QAAQ,IAAI,aAAa,OAAO,OAAO,MAAM;IAC/C;IACA,OAAO;GACT;EACF;EACA,MAAM;GACJ,eAAe,QAAQ;IACrB,OAAO,OAAO;IACd,aAAa,kBAAkB;GACjC;GACA,mBAAmB,aAAa;IAC9B,IAAI,WAAW,QAAQ,MAAM,iBAC3B,OAAO,WAAW,OAAO,KAAK,oBAAoB,YAAY;IAEhE,OAAO;GACT;EACF;CACF;AACF"}
@@ -5,5 +5,5 @@ export { createRouterPluginContext } from './core/router-plugin-context.js';
5
5
  export type { Config, ConfigInput, ConfigOutput, CodeSplittingOptions, DeletableNodes, HmrOptions, } from './core/config.js';
6
6
  export type { RouterPluginContext } from './core/router-plugin-context.js';
7
7
  export { getObjectPropertyKeyName } from './core/utils.js';
8
- export type { ReferenceRouteCompilerPlugin, ReferenceRouteCompilerPluginContext, } from './core/code-splitter/plugins.js';
8
+ export type { CodeSplitCompilerPlugin, ReferenceRouteCompilerPlugin, ReferenceRouteCompilerPluginContext, VirtualRouteSplitNodeCompilerPluginContext, } from './core/code-splitter/plugins.js';
9
9
  export { tsrSplit, splitRouteIdentNodes, defaultCodeSplitGroupings, } from './core/constants.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-plugin",
3
- "version": "1.168.21",
3
+ "version": "1.168.23",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -107,8 +107,8 @@
107
107
  "unplugin": "^3.0.0",
108
108
  "zod": "^4.4.3",
109
109
  "@tanstack/router-core": "1.171.15",
110
- "@tanstack/router-generator": "1.167.20",
111
- "@tanstack/router-utils": "1.162.2"
110
+ "@tanstack/router-utils": "1.162.2",
111
+ "@tanstack/router-generator": "1.167.21"
112
112
  },
113
113
  "devDependencies": {
114
114
  "@types/babel__core": "^7.20.5",
@@ -25,8 +25,8 @@ import { createRouteHmrStatement } from '../hmr'
25
25
  import { getObjectPropertyKeyName } from '../utils'
26
26
  import { getFrameworkOptions } from './framework-options'
27
27
  import type {
28
+ CodeSplitCompilerPlugin,
28
29
  CompileCodeSplitReferenceRouteOptions,
29
- ReferenceRouteCompilerPlugin,
30
30
  } from './plugins'
31
31
  import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils'
32
32
  import type { CodeSplitGroupings, SplitRouteIdentNodes } from '../constants'
@@ -364,7 +364,7 @@ function removeSharedDeclarations(ast: t.File, sharedBindings: Set<string>) {
364
364
  export function compileCodeSplitReferenceRoute(
365
365
  opts: ParseAstOptions &
366
366
  CompileCodeSplitReferenceRouteOptions & {
367
- compilerPlugins?: Array<ReferenceRouteCompilerPlugin>
367
+ compilerPlugins?: Array<CodeSplitCompilerPlugin>
368
368
  },
369
369
  ): GeneratorResult | null {
370
370
  const ast = parseAst(opts)
@@ -879,6 +879,7 @@ export function compileCodeSplitVirtualRoute(
879
879
  splitTargets: Array<SplitRouteIdentNodes>
880
880
  filename: string
881
881
  sharedBindings?: Set<string>
882
+ compilerPlugins?: Array<CodeSplitCompilerPlugin>
882
883
  },
883
884
  ): GeneratorResult {
884
885
  const ast = parseAst(opts)
@@ -1015,6 +1016,14 @@ export function compileCodeSplitVirtualRoute(
1015
1016
 
1016
1017
  // Add the node to the program
1017
1018
  if (splitNode) {
1019
+ for (const plugin of opts.compilerPlugins ?? []) {
1020
+ plugin.onVirtualRouteSplitNode?.({
1021
+ programPath,
1022
+ splitNode,
1023
+ splitNodeMeta: splitMeta,
1024
+ })
1025
+ }
1026
+
1018
1027
  if (t.isFunctionDeclaration(splitNode)) {
1019
1028
  // an anonymous function declaration should only happen for `export default function() {...}`
1020
1029
  // so we should never get here
@@ -1023,6 +1032,7 @@ export function compileCodeSplitVirtualRoute(
1023
1032
  `Function declaration for "${SPLIT_TYPE}" must have an identifier.`,
1024
1033
  )
1025
1034
  }
1035
+
1026
1036
  splitMeta.shouldRemoveNode = false
1027
1037
  splitMeta.localExporterIdent = splitNode.id.name
1028
1038
  } else if (
@@ -1,27 +1,23 @@
1
1
  import { createReactRefreshIgnoredRouteExportsPlugin } from './react-refresh-ignored-route-exports'
2
2
  import { createReactRefreshRouteComponentsPlugin } from './react-refresh-route-components'
3
3
  import { createReactStableHmrSplitRouteComponentsPlugin } from './react-stable-hmr-split-route-components'
4
- import type { ReferenceRouteCompilerPlugin } from '../plugins'
4
+ import type { CodeSplitCompilerPlugin } from '../plugins'
5
5
  import type { Config, HmrStyle } from '../../config'
6
6
 
7
- export function getReferenceRouteCompilerPlugins(opts: {
7
+ export function getFrameworkHmrCompilerPlugins(opts: {
8
8
  targetFramework: Config['target']
9
- addHmr?: boolean
10
9
  hmrStyle?: HmrStyle
11
- }): Array<ReferenceRouteCompilerPlugin> | undefined {
10
+ }): Array<CodeSplitCompilerPlugin> | undefined {
12
11
  switch (opts.targetFramework) {
13
12
  case 'react': {
14
- if (opts.addHmr) {
15
- const hmrStyle = opts.hmrStyle ?? 'vite'
16
- return [
17
- ...(hmrStyle === 'vite'
18
- ? [createReactRefreshIgnoredRouteExportsPlugin()]
19
- : []),
20
- createReactRefreshRouteComponentsPlugin(),
21
- createReactStableHmrSplitRouteComponentsPlugin({ hmrStyle }),
22
- ]
23
- }
24
- return undefined
13
+ const hmrStyle = opts.hmrStyle ?? 'vite'
14
+ return [
15
+ ...(hmrStyle === 'vite'
16
+ ? [createReactRefreshIgnoredRouteExportsPlugin()]
17
+ : []),
18
+ createReactRefreshRouteComponentsPlugin(),
19
+ createReactStableHmrSplitRouteComponentsPlugin({ hmrStyle }),
20
+ ]
25
21
  }
26
22
  default:
27
23
  return undefined
@@ -13,29 +13,74 @@ const REACT_REFRESH_ROUTE_COMPONENT_IDENTS = new Set([
13
13
  'notFoundComponent',
14
14
  ])
15
15
 
16
- function hoistInlineRouteComponents(ctx: {
16
+ type RouteComponentContext = {
17
17
  programPath: Parameters<typeof getUniqueProgramIdentifier>[0]
18
18
  insertionPath: { insertBefore: (nodes: Array<t.VariableDeclaration>) => void }
19
19
  routeOptions: t.ObjectExpression
20
- }) {
20
+ }
21
+
22
+ function isReactComponentName(name: string) {
23
+ const firstCharacter = name[0]
24
+
25
+ return (
26
+ firstCharacter !== undefined &&
27
+ firstCharacter >= 'A' &&
28
+ firstCharacter <= 'Z'
29
+ )
30
+ }
31
+
32
+ function getRouteComponentKey(prop: t.ObjectProperty) {
33
+ const key = getObjectPropertyKeyName(prop)
34
+
35
+ return key && REACT_REFRESH_ROUTE_COMPONENT_IDENTS.has(key) ? key : undefined
36
+ }
37
+
38
+ function prepareRouteComponentsForReactRefresh(ctx: RouteComponentContext) {
21
39
  const hoistedDeclarations: Array<t.VariableDeclaration> = []
40
+ let modified = false
22
41
 
23
- ctx.routeOptions.properties.forEach((prop) => {
42
+ for (const prop of ctx.routeOptions.properties) {
24
43
  if (!t.isObjectProperty(prop)) {
25
- return
44
+ continue
26
45
  }
27
46
 
28
- const key = getObjectPropertyKeyName(prop)
47
+ const key = getRouteComponentKey(prop)
29
48
 
30
- if (!key || !REACT_REFRESH_ROUTE_COMPONENT_IDENTS.has(key)) {
31
- return
49
+ if (!key) {
50
+ continue
51
+ }
52
+
53
+ if (t.isIdentifier(prop.value)) {
54
+ if (isReactComponentName(prop.value.name)) {
55
+ continue
56
+ }
57
+
58
+ const bindingNode = ctx.programPath.scope.getBinding(prop.value.name)
59
+ ?.path.node
60
+ const isLocalComponentBinding =
61
+ t.isFunctionDeclaration(bindingNode) ||
62
+ t.isClassDeclaration(bindingNode) ||
63
+ t.isVariableDeclarator(bindingNode)
64
+
65
+ if (!isLocalComponentBinding) {
66
+ continue
67
+ }
68
+
69
+ const componentIdentifier = getUniqueProgramIdentifier(
70
+ ctx.programPath,
71
+ `TSR${key[0]!.toUpperCase()}${key.slice(1)}`,
72
+ )
73
+
74
+ ctx.programPath.scope.rename(prop.value.name, componentIdentifier.name)
75
+ modified = true
76
+ continue
32
77
  }
33
78
 
34
79
  if (
35
80
  !t.isArrowFunctionExpression(prop.value) &&
36
81
  !t.isFunctionExpression(prop.value)
37
82
  ) {
38
- return
83
+ continue
39
84
  }
40
85
 
41
86
  const hoistedIdentifier = getUniqueProgramIdentifier(
@@ -50,14 +95,14 @@ function hoistInlineRouteComponents(ctx: {
50
95
  )
51
96
 
52
97
  prop.value = t.cloneNode(hoistedIdentifier)
53
- })
98
+ modified = true
99
+ }
54
100
 
55
- if (hoistedDeclarations.length === 0) {
56
- return false
101
+ if (hoistedDeclarations.length > 0) {
102
+ ctx.insertionPath.insertBefore(hoistedDeclarations)
57
103
  }
58
104
 
59
- ctx.insertionPath.insertBefore(hoistedDeclarations)
60
- return true
105
+ return modified
61
106
  }
62
107
 
63
108
  export function createReactRefreshRouteComponentsPlugin(): ReferenceRouteCompilerPlugin {
@@ -66,27 +111,32 @@ export function createReactRefreshRouteComponentsPlugin(): ReferenceRouteCompile
66
111
  getStableRouteOptionKeys() {
67
112
  return [...REACT_REFRESH_ROUTE_COMPONENT_IDENTS]
68
113
  },
69
- onUnsplittableRoute(ctx) {
70
- if (!ctx.opts.addHmr) {
71
- return
72
- }
73
-
74
- if (hoistInlineRouteComponents(ctx)) {
114
+ onAddHmr(ctx) {
115
+ if (prepareRouteComponentsForReactRefresh(ctx)) {
75
116
  return { modified: true }
76
117
  }
77
118
 
78
119
  return
79
120
  },
80
- onAddHmr(ctx) {
81
- if (!ctx.opts.addHmr) {
121
+ onVirtualRouteSplitNode(ctx) {
122
+ if (
123
+ ctx.splitNodeMeta.splitStrategy !== 'lazyRouteComponent' ||
124
+ !t.isFunctionDeclaration(ctx.splitNode) ||
125
+ !ctx.splitNode.id ||
126
+ isReactComponentName(ctx.splitNode.id.name)
127
+ ) {
82
128
  return
83
129
  }
84
130
 
85
- if (hoistInlineRouteComponents(ctx)) {
86
- return { modified: true }
87
- }
131
+ const componentIdentifier = getUniqueProgramIdentifier(
132
+ ctx.programPath,
133
+ ctx.splitNodeMeta.localExporterIdent,
134
+ )
88
135
 
89
- return
136
+ ctx.programPath.scope.rename(
137
+ ctx.splitNode.id.name,
138
+ componentIdentifier.name,
139
+ )
90
140
  },
91
141
  }
92
142
  }
@@ -40,7 +40,13 @@ export type ReferenceRouteCompilerPluginResult = {
40
40
  modified?: boolean
41
41
  }
42
42
 
43
- export type ReferenceRouteCompilerPlugin = {
43
+ export type VirtualRouteSplitNodeCompilerPluginContext = {
44
+ programPath: babel.NodePath<t.Program>
45
+ splitNode: t.Node
46
+ splitNodeMeta: SplitNodeMeta
47
+ }
48
+
49
+ export type CodeSplitCompilerPlugin = {
44
50
  name: string
45
51
  getStableRouteOptionKeys?: () => Array<string>
46
52
  onRouteOptions?: (
@@ -55,4 +61,9 @@ export type ReferenceRouteCompilerPlugin = {
55
61
  onSplitRouteProperty?: (
56
62
  ctx: ReferenceRouteSplitPropertyCompilerPluginContext,
57
63
  ) => void | t.Expression
64
+ onVirtualRouteSplitNode?: (
65
+ ctx: VirtualRouteSplitNodeCompilerPluginContext,
66
+ ) => void
58
67
  }
68
+
69
+ export type ReferenceRouteCompilerPlugin = CodeSplitCompilerPlugin
@@ -9,7 +9,7 @@ import type {
9
9
  RouteIds,
10
10
  } from '@tanstack/router-core'
11
11
  import type { CodeSplitGroupings } from './constants'
12
- import type { ReferenceRouteCompilerPlugin } from './code-splitter/plugins'
12
+ import type { CodeSplitCompilerPlugin } from './code-splitter/plugins'
13
13
 
14
14
  export const splitGroupingsSchema = z
15
15
  .array(
@@ -76,7 +76,7 @@ export type CodeSplittingOptions = {
76
76
  * Internal compiler plugins used by framework integrations.
77
77
  * @internal
78
78
  */
79
- compilerPlugins?: Array<ReferenceRouteCompilerPlugin>
79
+ compilerPlugins?: Array<CodeSplitCompilerPlugin>
80
80
  }
81
81
 
82
82
  export type HmrStyle = 'vite' | 'webpack'