@tanstack/router-plugin 1.167.22 → 1.167.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.
- package/dist/cjs/core/code-splitter/compilers.cjs +8 -4
- package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs +8 -5
- package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/framework-plugins.d.cts +2 -2
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.cjs +5 -9
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/react-refresh-ignored-route-exports.d.cts +1 -3
- package/dist/cjs/core/code-splitter/plugins/react-stable-hmr-split-route-components.cjs +6 -4
- package/dist/cjs/core/code-splitter/plugins/react-stable-hmr-split-route-components.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/plugins/react-stable-hmr-split-route-components.d.cts +3 -2
- package/dist/cjs/core/code-splitter/plugins.d.cts +3 -2
- package/dist/cjs/core/config.cjs +1 -1
- package/dist/cjs/core/config.cjs.map +1 -1
- package/dist/cjs/core/config.d.cts +26 -18
- package/dist/cjs/core/{route-hmr-statement.cjs → hmr/handle-route-update.cjs} +39 -25
- package/dist/cjs/core/hmr/handle-route-update.cjs.map +1 -0
- package/dist/cjs/core/hmr/handle-route-update.d.cts +1 -0
- package/dist/cjs/core/hmr/index.d.cts +5 -0
- package/dist/cjs/core/hmr/select-adapter.cjs +20 -0
- package/dist/cjs/core/hmr/select-adapter.cjs.map +1 -0
- package/dist/cjs/core/hmr/select-adapter.d.cts +13 -0
- package/dist/cjs/core/hmr/vite-adapter.cjs +36 -0
- package/dist/cjs/core/hmr/vite-adapter.cjs.map +1 -0
- package/dist/cjs/core/hmr/vite-adapter.d.cts +12 -0
- package/dist/cjs/core/hmr/webpack-adapter.cjs +64 -0
- package/dist/cjs/core/hmr/webpack-adapter.cjs.map +1 -0
- package/dist/cjs/core/hmr/webpack-adapter.d.cts +20 -0
- package/dist/cjs/core/router-code-splitter-plugin.cjs +5 -5
- package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
- package/dist/cjs/core/router-composed-plugin.cjs +2 -1
- package/dist/cjs/core/router-composed-plugin.cjs.map +1 -1
- package/dist/cjs/core/router-composed-plugin.d.cts +1 -1
- package/dist/cjs/core/router-hmr-plugin.cjs +17 -11
- package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
- package/dist/cjs/esbuild.d.cts +14 -14
- package/dist/cjs/rspack.cjs +22 -3
- package/dist/cjs/rspack.cjs.map +1 -1
- package/dist/cjs/rspack.d.cts +3 -3
- package/dist/cjs/vite.d.cts +14 -14
- package/dist/cjs/webpack.cjs +19 -3
- package/dist/cjs/webpack.cjs.map +1 -1
- package/dist/cjs/webpack.d.cts +3 -3
- package/dist/esm/core/code-splitter/compilers.js +7 -3
- package/dist/esm/core/code-splitter/compilers.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins/framework-plugins.d.ts +2 -2
- package/dist/esm/core/code-splitter/plugins/framework-plugins.js +8 -5
- package/dist/esm/core/code-splitter/plugins/framework-plugins.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.d.ts +1 -3
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.js +4 -8
- package/dist/esm/core/code-splitter/plugins/react-refresh-ignored-route-exports.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins/react-stable-hmr-split-route-components.d.ts +3 -2
- package/dist/esm/core/code-splitter/plugins/react-stable-hmr-split-route-components.js +5 -3
- package/dist/esm/core/code-splitter/plugins/react-stable-hmr-split-route-components.js.map +1 -1
- package/dist/esm/core/code-splitter/plugins.d.ts +3 -2
- package/dist/esm/core/config.d.ts +26 -18
- package/dist/esm/core/config.js +1 -1
- package/dist/esm/core/config.js.map +1 -1
- package/dist/esm/core/hmr/handle-route-update.d.ts +1 -0
- package/dist/esm/core/{route-hmr-statement.js → hmr/handle-route-update.js} +39 -23
- package/dist/esm/core/hmr/handle-route-update.js.map +1 -0
- package/dist/esm/core/hmr/index.d.ts +5 -0
- package/dist/esm/core/hmr/select-adapter.d.ts +13 -0
- package/dist/esm/core/hmr/select-adapter.js +20 -0
- package/dist/esm/core/hmr/select-adapter.js.map +1 -0
- package/dist/esm/core/hmr/vite-adapter.d.ts +12 -0
- package/dist/esm/core/hmr/vite-adapter.js +34 -0
- package/dist/esm/core/hmr/vite-adapter.js.map +1 -0
- package/dist/esm/core/hmr/webpack-adapter.d.ts +20 -0
- package/dist/esm/core/hmr/webpack-adapter.js +62 -0
- package/dist/esm/core/hmr/webpack-adapter.js.map +1 -0
- package/dist/esm/core/router-code-splitter-plugin.js +5 -5
- package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
- package/dist/esm/core/router-composed-plugin.d.ts +1 -1
- package/dist/esm/core/router-composed-plugin.js +2 -1
- package/dist/esm/core/router-composed-plugin.js.map +1 -1
- package/dist/esm/core/router-hmr-plugin.js +17 -11
- package/dist/esm/core/router-hmr-plugin.js.map +1 -1
- package/dist/esm/esbuild.d.ts +14 -14
- package/dist/esm/rspack.d.ts +3 -3
- package/dist/esm/rspack.js +22 -3
- package/dist/esm/rspack.js.map +1 -1
- package/dist/esm/vite.d.ts +14 -14
- package/dist/esm/webpack.d.ts +3 -3
- package/dist/esm/webpack.js +19 -3
- package/dist/esm/webpack.js.map +1 -1
- package/package.json +5 -5
- package/src/core/code-splitter/compilers.ts +4 -2
- package/src/core/code-splitter/plugins/framework-plugins.ts +7 -8
- package/src/core/code-splitter/plugins/react-refresh-ignored-route-exports.ts +2 -8
- package/src/core/code-splitter/plugins/react-stable-hmr-split-route-components.ts +10 -6
- package/src/core/code-splitter/plugins.ts +3 -2
- package/src/core/config.ts +11 -2
- package/src/core/{route-hmr-statement.ts → hmr/handle-route-update.ts} +85 -39
- package/src/core/hmr/index.ts +5 -0
- package/src/core/hmr/select-adapter.ts +32 -0
- package/src/core/hmr/vite-adapter.ts +47 -0
- package/src/core/hmr/webpack-adapter.ts +110 -0
- package/src/core/router-code-splitter-plugin.ts +5 -7
- package/src/core/router-composed-plugin.ts +8 -3
- package/src/core/router-hmr-plugin.ts +12 -9
- package/src/rspack.ts +37 -9
- package/src/webpack.ts +22 -9
- package/dist/cjs/core/hmr-hot-expression.cjs +0 -27
- package/dist/cjs/core/hmr-hot-expression.cjs.map +0 -1
- package/dist/cjs/core/hmr-hot-expression.d.cts +0 -6
- package/dist/cjs/core/route-hmr-statement.cjs.map +0 -1
- package/dist/cjs/core/route-hmr-statement.d.cts +0 -4
- package/dist/esm/core/hmr-hot-expression.d.ts +0 -6
- package/dist/esm/core/hmr-hot-expression.js +0 -23
- package/dist/esm/core/hmr-hot-expression.js.map +0 -1
- package/dist/esm/core/route-hmr-statement.d.ts +0 -4
- package/dist/esm/core/route-hmr-statement.js.map +0 -1
- package/src/core/hmr-hot-expression.ts +0 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-refresh-ignored-route-exports.cjs","names":[],"sources":["../../../../../src/core/code-splitter/plugins/react-refresh-ignored-route-exports.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport * as t from '@babel/types'\nimport {
|
|
1
|
+
{"version":3,"file":"react-refresh-ignored-route-exports.cjs","names":[],"sources":["../../../../../src/core/code-splitter/plugins/react-refresh-ignored-route-exports.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport * as t from '@babel/types'\nimport { getUniqueProgramIdentifier } from '../../utils'\nimport type { ReferenceRouteCompilerPlugin } from '../plugins'\n\nconst buildReactRefreshIgnoredRouteExportsStatements = template.statements(\n `\nconst hot = import.meta.hot\nif (hot && typeof window !== 'undefined') {\n ;(hot.data ??= {})\n const tsrReactRefresh = window.__TSR_REACT_REFRESH__ ??= (() => {\n const ignoredExportsById = new Map()\n const previousGetIgnoredExports = window.__getReactRefreshIgnoredExports\n\n window.__getReactRefreshIgnoredExports = (ctx) => {\n const ignoredExports = previousGetIgnoredExports?.(ctx) ?? []\n const moduleIgnored = ignoredExportsById.get(ctx.id) ?? []\n return [...ignoredExports, ...moduleIgnored]\n }\n\n return {\n ignoredExportsById,\n }\n })()\n\n tsrReactRefresh.ignoredExportsById.set(%%moduleId%%, ['Route'])\n}\n`,\n { syntacticPlaceholders: true },\n)\n\n/**\n * A trivial component-shaped export that gives `@vitejs/plugin-react` a valid\n * Fast Refresh boundary. Without at least one non-ignored component export,\n * the module would be invalidated (full page reload) on every update even\n * though our custom route HMR handler already manages the update.\n */\nconst buildRefreshAnchorStatement = template.statement(\n `export function %%anchorName%%() { return null }`,\n { syntacticPlaceholders: true },\n)\n\nexport function createReactRefreshIgnoredRouteExportsPlugin(): ReferenceRouteCompilerPlugin {\n return {\n name: 'react-refresh-ignored-route-exports',\n onAddHmr(ctx) {\n const anchorName = getUniqueProgramIdentifier(\n ctx.programPath,\n 'TSRFastRefreshAnchor',\n )\n\n ctx.programPath.pushContainer(\n 'body',\n buildReactRefreshIgnoredRouteExportsStatements({\n moduleId: t.stringLiteral(ctx.opts.id),\n }),\n )\n\n ctx.programPath.pushContainer(\n 'body',\n buildRefreshAnchorStatement({ anchorName }),\n )\n\n return { modified: true }\n },\n }\n}\n"],"mappings":";;;;;;;AAKA,IAAM,iDAAiD,gBAAS,WAC9D;;;;;;;;;;;;;;;;;;;;;GAsBA,EAAE,uBAAuB,MAAM,CAChC;;;;;;;AAQD,IAAM,8BAA8B,gBAAS,UAC3C,oDACA,EAAE,uBAAuB,MAAM,CAChC;AAED,SAAgB,8CAA4E;AAC1F,QAAO;EACL,MAAM;EACN,SAAS,KAAK;GACZ,MAAM,aAAa,cAAA,2BACjB,IAAI,aACJ,uBACD;AAED,OAAI,YAAY,cACd,QACA,+CAA+C,EAC7C,UAAU,aAAE,cAAc,IAAI,KAAK,GAAG,EACvC,CAAC,CACH;AAED,OAAI,YAAY,cACd,QACA,4BAA4B,EAAE,YAAY,CAAC,CAC5C;AAED,UAAO,EAAE,UAAU,MAAM;;EAE5B"}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
1
|
import { ReferenceRouteCompilerPlugin } from '../plugins.cjs';
|
|
2
|
-
export declare function createReactRefreshIgnoredRouteExportsPlugin(
|
|
3
|
-
hotExpression?: string;
|
|
4
|
-
}): ReferenceRouteCompilerPlugin;
|
|
2
|
+
export declare function createReactRefreshIgnoredRouteExportsPlugin(): ReferenceRouteCompilerPlugin;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
const require_runtime = require("../../../_virtual/_rolldown/runtime.cjs");
|
|
2
|
-
const require_hmr_hot_expression = require("../../hmr-hot-expression.cjs");
|
|
3
2
|
const require_utils = require("../../utils.cjs");
|
|
4
|
-
let _babel_template = require("@babel/template");
|
|
5
|
-
_babel_template = require_runtime.__toESM(_babel_template);
|
|
6
3
|
let _babel_types = require("@babel/types");
|
|
7
4
|
_babel_types = require_runtime.__toESM(_babel_types);
|
|
5
|
+
let _babel_template = require("@babel/template");
|
|
6
|
+
_babel_template = require_runtime.__toESM(_babel_template);
|
|
8
7
|
//#region src/core/code-splitter/plugins/react-stable-hmr-split-route-components.ts
|
|
9
8
|
function capitalizeIdentifier(str) {
|
|
10
9
|
return str[0].toUpperCase() + str.slice(1);
|
|
@@ -22,6 +21,9 @@ var buildStableSplitComponentStatements = _babel_template.statements(`
|
|
|
22
21
|
((%%hotExpression%%).data ??= {})[%%hotDataKey%%] = %%stableComponentIdent%%
|
|
23
22
|
}
|
|
24
23
|
`, { syntacticPlaceholders: true });
|
|
24
|
+
function hotExpressionAstFor(hmrStyle) {
|
|
25
|
+
return _babel_template.expression.ast(hmrStyle === "webpack" ? "import.meta.webpackHot" : "import.meta.hot");
|
|
26
|
+
}
|
|
25
27
|
function createReactStableHmrSplitRouteComponentsPlugin(opts) {
|
|
26
28
|
return {
|
|
27
29
|
name: "react-stable-hmr-split-route-components",
|
|
@@ -32,7 +34,7 @@ function createReactStableHmrSplitRouteComponentsPlugin(opts) {
|
|
|
32
34
|
ctx.insertionPath.insertBefore(buildStableSplitComponentStatements({
|
|
33
35
|
stableComponentIdent,
|
|
34
36
|
hotDataKey: _babel_types.stringLiteral(hotDataKey),
|
|
35
|
-
hotExpression:
|
|
37
|
+
hotExpression: hotExpressionAstFor(opts.hmrStyle),
|
|
36
38
|
lazyRouteComponentIdent: _babel_types.identifier(ctx.lazyRouteComponentIdent),
|
|
37
39
|
localImporterIdent: _babel_types.identifier(ctx.splitNodeMeta.localImporterIdent),
|
|
38
40
|
exporterIdent: _babel_types.stringLiteral(ctx.splitNodeMeta.exporterIdent)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-stable-hmr-split-route-components.cjs","names":[],"sources":["../../../../../src/core/code-splitter/plugins/react-stable-hmr-split-route-components.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport * as t from '@babel/types'\nimport {
|
|
1
|
+
{"version":3,"file":"react-stable-hmr-split-route-components.cjs","names":[],"sources":["../../../../../src/core/code-splitter/plugins/react-stable-hmr-split-route-components.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport * as t from '@babel/types'\nimport { getUniqueProgramIdentifier } from '../../utils'\nimport type { HmrStyle } from '../../config'\nimport type { ReferenceRouteCompilerPlugin } from '../plugins'\n\nfunction capitalizeIdentifier(str: string) {\n return str[0]!.toUpperCase() + str.slice(1)\n}\n\nfunction createHotDataKey(exportName: string) {\n return `tsr-split-component:${exportName}`\n}\n\nconst buildStableSplitComponentStatements = template.statements(\n `\n const %%stableComponentIdent%% = (() => {\n const hot = %%hotExpression%%\n const hotData = hot ? (hot.data ??= {}) : undefined\n return hotData?.[%%hotDataKey%%] ?? %%lazyRouteComponentIdent%%(%%localImporterIdent%%, %%exporterIdent%%)\n })()\n if (%%hotExpression%%) {\n ((%%hotExpression%%).data ??= {})[%%hotDataKey%%] = %%stableComponentIdent%%\n }\n `,\n {\n syntacticPlaceholders: true,\n },\n)\n\nfunction hotExpressionAstFor(hmrStyle: HmrStyle): t.Expression {\n return template.expression.ast(\n hmrStyle === 'webpack' ? 'import.meta.webpackHot' : 'import.meta.hot',\n )\n}\n\nexport function createReactStableHmrSplitRouteComponentsPlugin(opts: {\n hmrStyle: HmrStyle\n}): ReferenceRouteCompilerPlugin {\n return {\n name: 'react-stable-hmr-split-route-components',\n onSplitRouteProperty(ctx) {\n if (ctx.splitNodeMeta.splitStrategy !== 'lazyRouteComponent') {\n return\n }\n\n const stableComponentIdent = getUniqueProgramIdentifier(\n ctx.programPath,\n `TSRSplit${capitalizeIdentifier(ctx.splitNodeMeta.exporterIdent)}`,\n )\n\n const hotDataKey = createHotDataKey(ctx.splitNodeMeta.exporterIdent)\n\n ctx.insertionPath.insertBefore(\n buildStableSplitComponentStatements({\n stableComponentIdent,\n hotDataKey: t.stringLiteral(hotDataKey),\n hotExpression: hotExpressionAstFor(opts.hmrStyle),\n lazyRouteComponentIdent: t.identifier(ctx.lazyRouteComponentIdent),\n localImporterIdent: t.identifier(\n ctx.splitNodeMeta.localImporterIdent,\n ),\n exporterIdent: t.stringLiteral(ctx.splitNodeMeta.exporterIdent),\n }),\n )\n\n return t.identifier(stableComponentIdent.name)\n },\n }\n}\n"],"mappings":";;;;;;;AAMA,SAAS,qBAAqB,KAAa;AACzC,QAAO,IAAI,GAAI,aAAa,GAAG,IAAI,MAAM,EAAE;;AAG7C,SAAS,iBAAiB,YAAoB;AAC5C,QAAO,uBAAuB;;AAGhC,IAAM,sCAAsC,gBAAS,WACnD;;;;;;;;;KAUA,EACE,uBAAuB,MACxB,CACF;AAED,SAAS,oBAAoB,UAAkC;AAC7D,QAAO,gBAAS,WAAW,IACzB,aAAa,YAAY,2BAA2B,kBACrD;;AAGH,SAAgB,+CAA+C,MAE9B;AAC/B,QAAO;EACL,MAAM;EACN,qBAAqB,KAAK;AACxB,OAAI,IAAI,cAAc,kBAAkB,qBACtC;GAGF,MAAM,uBAAuB,cAAA,2BAC3B,IAAI,aACJ,WAAW,qBAAqB,IAAI,cAAc,cAAc,GACjE;GAED,MAAM,aAAa,iBAAiB,IAAI,cAAc,cAAc;AAEpE,OAAI,cAAc,aAChB,oCAAoC;IAClC;IACA,YAAY,aAAE,cAAc,WAAW;IACvC,eAAe,oBAAoB,KAAK,SAAS;IACjD,yBAAyB,aAAE,WAAW,IAAI,wBAAwB;IAClE,oBAAoB,aAAE,WACpB,IAAI,cAAc,mBACnB;IACD,eAAe,aAAE,cAAc,IAAI,cAAc,cAAc;IAChE,CAAC,CACH;AAED,UAAO,aAAE,WAAW,qBAAqB,KAAK;;EAEjD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { HmrStyle } from '../../config.cjs';
|
|
1
2
|
import { ReferenceRouteCompilerPlugin } from '../plugins.cjs';
|
|
2
|
-
export declare function createReactStableHmrSplitRouteComponentsPlugin(opts
|
|
3
|
-
|
|
3
|
+
export declare function createReactStableHmrSplitRouteComponentsPlugin(opts: {
|
|
4
|
+
hmrStyle: HmrStyle;
|
|
4
5
|
}): ReferenceRouteCompilerPlugin;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as babel } from '@babel/core';
|
|
2
|
-
import { Config, DeletableNodes } from '../config.cjs';
|
|
2
|
+
import { Config, DeletableNodes, HmrStyle } from '../config.cjs';
|
|
3
3
|
import { CodeSplitGroupings } from '../constants.cjs';
|
|
4
4
|
import { SplitNodeMeta } from './types.cjs';
|
|
5
5
|
import type * as t from '@babel/types';
|
|
@@ -10,7 +10,8 @@ export type CompileCodeSplitReferenceRouteOptions = {
|
|
|
10
10
|
filename: string;
|
|
11
11
|
id: string;
|
|
12
12
|
addHmr?: boolean;
|
|
13
|
-
|
|
13
|
+
hmrStyle?: HmrStyle;
|
|
14
|
+
hmrRouteId?: string;
|
|
14
15
|
sharedBindings?: Set<string>;
|
|
15
16
|
};
|
|
16
17
|
export type ReferenceRouteCompilerPluginContext = {
|
package/dist/cjs/core/config.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var configSchema = _tanstack_router_generator.configSchema.extend({
|
|
|
27
27
|
return codeSplittingOptionsSchema.parse(v);
|
|
28
28
|
}).optional(),
|
|
29
29
|
plugin: zod.z.object({
|
|
30
|
-
hmr: zod.z.object({
|
|
30
|
+
hmr: zod.z.object({ style: zod.z.enum(["vite", "webpack"]).optional() }).optional(),
|
|
31
31
|
vite: zod.z.object({ environmentName: zod.z.string().optional() }).optional()
|
|
32
32
|
}).optional()
|
|
33
33
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","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'\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\nexport type HmrOptions = {\n
|
|
1
|
+
{"version":3,"file":"config.cjs","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'\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\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.function().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":";;;;AAYA,IAAa,uBAAuB,IAAA,EACjC,MACC,IAAA,EAAE,MACA,IAAA,EAAE,MAAM;CACN,IAAA,EAAE,QAAQ,SAAS;CACnB,IAAA,EAAE,QAAQ,YAAY;CACtB,IAAA,EAAE,QAAQ,mBAAmB;CAC7B,IAAA,EAAE,QAAQ,iBAAiB;CAC3B,IAAA,EAAE,QAAQ,oBAAoB;CAC/B,CAAC,CACH,EACD,EACE,SACE,oJACH,CACF,CACA,aAAa,KAAK,QAAQ;CACzB,MAAM,YAAY,IAAI,MAAM;AAK5B,KAJe,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,CAI3B,WAAW,UAAU,OAC9B,KAAI,SAAS;EACX,MAAM;EACN,SACE,kKACsB,KAAK,UAAU,IAAI,CAAC;EAC7C,CAAC;EAEJ;AA6CJ,IAAM,6BAA6B,IAAA,EAAE,OAAO;CAC1C,eAAe,IAAA,EAAE,UAAU,CAAC,UAAU;CACtC,iBAAiB,qBAAqB,UAAU;CAChD,aAAa,IAAA,EAAE,MAAM,IAAA,EAAE,QAAQ,CAAC,CAAC,UAAU;CAC3C,QAAQ,IAAA,EAAE,SAAS,CAAC,UAAU,CAAC,QAAQ,KAAK;CAC7C,CAAC;AAOF,IAAa,eAAe,2BAAA,aAAsB,OAAO;CACvD,uBAAuB,IAAA,EAAE,SAAS,CAAC,UAAU;CAC7C,sBAAsB,IAAA,EACnB,QAA8B,MAAM;AACnC,SAAO,2BAA2B,MAAM,EAAE;GAC1C,CACD,UAAU;CACb,QAAQ,IAAA,EACL,OAAO;EACN,KAAK,IAAA,EACF,OAAO,EACN,OAAO,IAAA,EAAE,KAAK,CAAC,QAAQ,UAAU,CAAC,CAAC,UAAU,EAC9C,CAAC,CACD,UAAU;EACb,MAAM,IAAA,EACH,OAAO,EACN,iBAAiB,IAAA,EAAE,QAAQ,CAAC,UAAU,EACvC,CAAC,CACD,UAAU;EACd,CAAC,CACD,UAAU;CACd,CAAC;AAEF,IAAa,aAAa,cAA+B,SAAiB;CACxE,MAAM,UAAA,GAAA,2BAAA,WAA4B,cAAc,KAAK;AAErD,QAAO,aAAa,MAAM;EAAE,GAAG;EAAc,GAAG;EAAQ,CAAC"}
|
|
@@ -28,8 +28,16 @@ export type CodeSplittingOptions = {
|
|
|
28
28
|
*/
|
|
29
29
|
addHmr?: boolean;
|
|
30
30
|
};
|
|
31
|
+
export type HmrStyle = 'vite' | 'webpack';
|
|
31
32
|
export type HmrOptions = {
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Selects the HMR runtime style to emit code for.
|
|
35
|
+
* - `'vite'` (default): ESM `import.meta.hot` with Vite accept-callback semantics.
|
|
36
|
+
* - `'webpack'`: `import.meta.webpackHot` with webpack / Rspack `module.hot` re-execution semantics.
|
|
37
|
+
*
|
|
38
|
+
* Bundler-specific plugin entries (e.g. `rspack.ts`, `webpack.ts`) set this explicitly.
|
|
39
|
+
*/
|
|
40
|
+
style?: HmrStyle;
|
|
33
41
|
};
|
|
34
42
|
type FileRouteKeys = keyof (Parameters<CreateFileRoute<any, any, any, any, any>>[0] & {});
|
|
35
43
|
export type DeletableNodes = FileRouteKeys | (string & {});
|
|
@@ -97,11 +105,11 @@ export declare const configSchema: z.ZodObject<{
|
|
|
97
105
|
codeSplittingOptions: z.ZodOptional<z.ZodType<CodeSplittingOptions, z.ZodTypeDef, CodeSplittingOptions>>;
|
|
98
106
|
plugin: z.ZodOptional<z.ZodObject<{
|
|
99
107
|
hmr: z.ZodOptional<z.ZodObject<{
|
|
100
|
-
|
|
108
|
+
style: z.ZodOptional<z.ZodEnum<["vite", "webpack"]>>;
|
|
101
109
|
}, "strip", z.ZodTypeAny, {
|
|
102
|
-
|
|
110
|
+
style?: "vite" | "webpack" | undefined;
|
|
103
111
|
}, {
|
|
104
|
-
|
|
112
|
+
style?: "vite" | "webpack" | undefined;
|
|
105
113
|
}>>;
|
|
106
114
|
vite: z.ZodOptional<z.ZodObject<{
|
|
107
115
|
environmentName: z.ZodOptional<z.ZodString>;
|
|
@@ -111,19 +119,19 @@ export declare const configSchema: z.ZodObject<{
|
|
|
111
119
|
environmentName?: string | undefined;
|
|
112
120
|
}>>;
|
|
113
121
|
}, "strip", z.ZodTypeAny, {
|
|
114
|
-
hmr?: {
|
|
115
|
-
hotExpression?: string | undefined;
|
|
116
|
-
} | undefined;
|
|
117
122
|
vite?: {
|
|
118
123
|
environmentName?: string | undefined;
|
|
119
124
|
} | undefined;
|
|
120
|
-
}, {
|
|
121
125
|
hmr?: {
|
|
122
|
-
|
|
126
|
+
style?: "vite" | "webpack" | undefined;
|
|
123
127
|
} | undefined;
|
|
128
|
+
}, {
|
|
124
129
|
vite?: {
|
|
125
130
|
environmentName?: string | undefined;
|
|
126
131
|
} | undefined;
|
|
132
|
+
hmr?: {
|
|
133
|
+
style?: "vite" | "webpack" | undefined;
|
|
134
|
+
} | undefined;
|
|
127
135
|
}>>;
|
|
128
136
|
}, "strip", z.ZodTypeAny, {
|
|
129
137
|
target: "react" | "solid" | "vue";
|
|
@@ -150,12 +158,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
150
158
|
enableRouteGeneration?: boolean | undefined;
|
|
151
159
|
codeSplittingOptions?: CodeSplittingOptions | undefined;
|
|
152
160
|
plugin?: {
|
|
153
|
-
hmr?: {
|
|
154
|
-
hotExpression?: string | undefined;
|
|
155
|
-
} | undefined;
|
|
156
161
|
vite?: {
|
|
157
162
|
environmentName?: string | undefined;
|
|
158
163
|
} | undefined;
|
|
164
|
+
hmr?: {
|
|
165
|
+
style?: "vite" | "webpack" | undefined;
|
|
166
|
+
} | undefined;
|
|
159
167
|
} | undefined;
|
|
160
168
|
virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
|
|
161
169
|
routeFilePrefix?: string | undefined;
|
|
@@ -175,12 +183,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
175
183
|
enableRouteGeneration?: boolean | undefined;
|
|
176
184
|
codeSplittingOptions?: CodeSplittingOptions | undefined;
|
|
177
185
|
plugin?: {
|
|
178
|
-
hmr?: {
|
|
179
|
-
hotExpression?: string | undefined;
|
|
180
|
-
} | undefined;
|
|
181
186
|
vite?: {
|
|
182
187
|
environmentName?: string | undefined;
|
|
183
188
|
} | undefined;
|
|
189
|
+
hmr?: {
|
|
190
|
+
style?: "vite" | "webpack" | undefined;
|
|
191
|
+
} | undefined;
|
|
184
192
|
} | undefined;
|
|
185
193
|
target?: "react" | "solid" | "vue" | undefined;
|
|
186
194
|
virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
|
|
@@ -243,12 +251,12 @@ export declare const getConfig: (inlineConfig: Partial<Config>, root: string) =>
|
|
|
243
251
|
enableRouteGeneration?: boolean | undefined;
|
|
244
252
|
codeSplittingOptions?: CodeSplittingOptions | undefined;
|
|
245
253
|
plugin?: {
|
|
246
|
-
hmr?: {
|
|
247
|
-
hotExpression?: string | undefined;
|
|
248
|
-
} | undefined;
|
|
249
254
|
vite?: {
|
|
250
255
|
environmentName?: string | undefined;
|
|
251
256
|
} | undefined;
|
|
257
|
+
hmr?: {
|
|
258
|
+
style?: "vite" | "webpack" | undefined;
|
|
259
|
+
} | undefined;
|
|
252
260
|
} | undefined;
|
|
253
261
|
virtualRouteConfig?: string | import('@tanstack/virtual-file-routes').VirtualRootRoute | undefined;
|
|
254
262
|
routeFilePrefix?: string | undefined;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const require_hmr_hot_expression = require("./hmr-hot-expression.cjs");
|
|
3
|
-
let _babel_template = require("@babel/template");
|
|
4
|
-
_babel_template = require_runtime.__toESM(_babel_template);
|
|
5
|
-
//#region src/core/route-hmr-statement.ts
|
|
1
|
+
//#region src/core/hmr/handle-route-update.ts
|
|
6
2
|
function handleRouteUpdate(routeId, newRoute) {
|
|
7
3
|
const router = window.__TSR_ROUTER__;
|
|
8
4
|
const oldRoute = router.routesById[routeId];
|
|
@@ -14,7 +10,9 @@ function handleRouteUpdate(routeId, newRoute) {
|
|
|
14
10
|
delete oldRoute.options[key];
|
|
15
11
|
}
|
|
16
12
|
});
|
|
17
|
-
"
|
|
13
|
+
const preserveComponentIdentity = "shellComponent" in oldRoute.options === "shellComponent" in newRoute.options;
|
|
14
|
+
const componentKeys = "__TSR_COMPONENT_TYPES__";
|
|
15
|
+
if (preserveComponentIdentity) componentKeys.forEach((key) => {
|
|
18
16
|
if (key in oldRoute.options && key in newRoute.options) newRoute.options[key] = oldRoute.options[key];
|
|
19
17
|
});
|
|
20
18
|
oldRoute.options = newRoute.options;
|
|
@@ -45,7 +43,10 @@ function handleRouteUpdate(routeId, newRoute) {
|
|
|
45
43
|
if (store) store.set((prev) => {
|
|
46
44
|
const next = { ...prev };
|
|
47
45
|
if (removedKeys.has("loader")) next.loaderData = void 0;
|
|
48
|
-
if (removedKeys.has("beforeLoad"))
|
|
46
|
+
if (removedKeys.has("beforeLoad")) {
|
|
47
|
+
next.__beforeLoadContext = void 0;
|
|
48
|
+
next.context = rebuildMatchContextWithoutBeforeLoad(next);
|
|
49
|
+
}
|
|
49
50
|
return next;
|
|
50
51
|
});
|
|
51
52
|
}
|
|
@@ -65,26 +66,39 @@ function handleRouteUpdate(routeId, newRoute) {
|
|
|
65
66
|
node.optional?.forEach((child) => walkReplaceSegmentTree(route, child));
|
|
66
67
|
node.wildcard?.forEach((child) => walkReplaceSegmentTree(route, child));
|
|
67
68
|
}
|
|
69
|
+
function getStoreMatch(matchId) {
|
|
70
|
+
return router.stores.pendingMatchStores.get(matchId)?.get() || router.stores.matchStores.get(matchId)?.get() || router.stores.cachedMatchStores.get(matchId)?.get();
|
|
71
|
+
}
|
|
72
|
+
function getMatchList(matchId) {
|
|
73
|
+
const pendingMatches = router.stores.pendingMatches.get();
|
|
74
|
+
if (pendingMatches.some((match) => match.id === matchId)) return pendingMatches;
|
|
75
|
+
const activeMatches = router.stores.matches.get();
|
|
76
|
+
if (activeMatches.some((match) => match.id === matchId)) return activeMatches;
|
|
77
|
+
const cachedMatches = router.stores.cachedMatches.get();
|
|
78
|
+
if (cachedMatches.some((match) => match.id === matchId)) return cachedMatches;
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
function getParentMatch(match) {
|
|
82
|
+
const matchList = getMatchList(match.id);
|
|
83
|
+
const matchIndex = matchList.findIndex((item) => item.id === match.id);
|
|
84
|
+
if (matchIndex <= 0) return;
|
|
85
|
+
const parentMatch = matchList[matchIndex - 1];
|
|
86
|
+
return getStoreMatch(parentMatch.id) || parentMatch;
|
|
87
|
+
}
|
|
88
|
+
function rebuildMatchContextWithoutBeforeLoad(match) {
|
|
89
|
+
const parentMatch = getParentMatch(match);
|
|
90
|
+
const getParentContext = router.getParentContext;
|
|
91
|
+
return {
|
|
92
|
+
...(getParentContext ? getParentContext.call(router, parentMatch) : parentMatch?.context ?? router.options.context) ?? {},
|
|
93
|
+
...match.__routeContext ?? {}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
68
96
|
}
|
|
69
97
|
var handleRouteUpdateStr = handleRouteUpdate.toString();
|
|
70
|
-
function
|
|
71
|
-
return
|
|
72
|
-
if (%%hotExpression%%) {
|
|
73
|
-
const hot = %%hotExpression%%
|
|
74
|
-
const hotData = hot.data ??= {}
|
|
75
|
-
hot.accept((newModule) => {
|
|
76
|
-
if (Route && newModule && newModule.Route) {
|
|
77
|
-
const routeId = hotData['tsr-route-id'] ?? Route.id
|
|
78
|
-
if (routeId) {
|
|
79
|
-
hotData['tsr-route-id'] = routeId
|
|
80
|
-
}
|
|
81
|
-
(${handleRouteUpdateStr.replace(/['"]__TSR_COMPONENT_TYPES__['"]/, JSON.stringify(stableRouteOptionKeys))})(routeId, newModule.Route)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
`, { syntacticPlaceholders: true })({ hotExpression: require_hmr_hot_expression.createHmrHotExpressionAst(opts?.hotExpression) });
|
|
98
|
+
function getHandleRouteUpdateCode(stableRouteOptionKeys) {
|
|
99
|
+
return handleRouteUpdateStr.replace(/['"]__TSR_COMPONENT_TYPES__['"]/, JSON.stringify(stableRouteOptionKeys));
|
|
86
100
|
}
|
|
87
101
|
//#endregion
|
|
88
|
-
exports.
|
|
102
|
+
exports.getHandleRouteUpdateCode = getHandleRouteUpdateCode;
|
|
89
103
|
|
|
90
|
-
//# sourceMappingURL=route-
|
|
104
|
+
//# sourceMappingURL=handle-route-update.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-route-update.cjs","names":[],"sources":["../../../../src/core/hmr/handle-route-update.ts"],"sourcesContent":["import type {\n AnyRoute,\n AnyRouteMatch,\n AnyRouter,\n RouterWritableStore,\n} from '@tanstack/router-core'\n\ntype AnyRouteWithPrivateProps = AnyRoute & {\n options: Record<string, unknown>\n _componentsPromise?: Promise<void>\n _lazyPromise?: Promise<void>\n update: (options: Record<string, unknown>) => unknown\n _path: string\n _id: string\n _fullPath: string\n _to: string\n}\n\ntype AnyRouterWithPrivateMaps = AnyRouter & {\n routesById: Record<string, AnyRoute>\n routesByPath: Record<string, AnyRoute>\n stores: AnyRouter['stores'] & {\n cachedMatchStores: Map<\n string,\n Pick<RouterWritableStore<AnyRouteMatch>, 'get' | 'set'>\n >\n pendingMatchStores: Map<\n string,\n Pick<RouterWritableStore<AnyRouteMatch>, 'get' | 'set'>\n >\n matchStores: Map<\n string,\n Pick<RouterWritableStore<AnyRouteMatch>, 'get' | 'set'>\n >\n }\n}\n\ntype AnyRouteMatchWithPrivateProps = AnyRouteMatch & {\n __beforeLoadContext?: unknown\n __routeContext?: Record<string, unknown>\n context?: Record<string, unknown>\n}\n\nfunction handleRouteUpdate(\n routeId: string,\n newRoute: AnyRouteWithPrivateProps,\n) {\n const router = window.__TSR_ROUTER__ as AnyRouterWithPrivateMaps\n const oldRoute = router.routesById[routeId] as\n | AnyRouteWithPrivateProps\n | undefined\n\n if (!oldRoute) {\n return\n }\n\n // Keys whose identity must remain stable to prevent React from\n // unmounting/remounting the component tree. React Fast Refresh already\n // handles hot-updating the function bodies of these components — our job\n // is only to update non-component route options (loader, head, etc.).\n // For code-split (splittable) routes, the lazyRouteComponent wrapper is\n // already cached in the bundler hot data so its identity is stable.\n // For unsplittable routes (e.g. root routes), the component is a plain\n // function reference that gets recreated on every module re-execution,\n // so we must explicitly preserve the old reference.\n const removedKeys = new Set<string>()\n Object.keys(oldRoute.options).forEach((key) => {\n if (!(key in newRoute.options)) {\n removedKeys.add(key)\n delete oldRoute.options[key]\n }\n })\n\n const oldHasShellComponent = 'shellComponent' in oldRoute.options\n const newHasShellComponent = 'shellComponent' in newRoute.options\n const preserveComponentIdentity =\n oldHasShellComponent === newHasShellComponent\n\n // Preserve component identity so React doesn't remount.\n // React Fast Refresh patches the function bodies in-place.\n const componentKeys = '__TSR_COMPONENT_TYPES__' as unknown as Array<string>\n if (preserveComponentIdentity) {\n componentKeys.forEach((key) => {\n if (key in oldRoute.options && key in newRoute.options) {\n newRoute.options[key] = oldRoute.options[key]\n }\n })\n }\n\n oldRoute.options = newRoute.options\n oldRoute.update(newRoute.options)\n oldRoute._componentsPromise = undefined\n oldRoute._lazyPromise = undefined\n\n router.routesById[oldRoute.id] = oldRoute\n router.routesByPath[oldRoute.fullPath] = oldRoute\n\n router.processedTree.matchCache.clear()\n router.processedTree.flatCache?.clear()\n router.processedTree.singleCache.clear()\n router.resolvePathCache.clear()\n walkReplaceSegmentTree(oldRoute, router.processedTree.segmentTree)\n\n const filter = (m: AnyRouteMatch) => m.routeId === oldRoute.id\n const activeMatch = router.stores.matches.get().find(filter)\n const pendingMatch = router.stores.pendingMatches.get().find(filter)\n const cachedMatches = router.stores.cachedMatches.get().filter(filter)\n\n if (activeMatch || pendingMatch || cachedMatches.length > 0) {\n // Clear stale match data for removed route options BEFORE invalidating.\n // Without this, router.invalidate() -> matchRoutes() reuses the existing\n // match from the store (via ...existingMatch spread) and the stale\n // loaderData / __beforeLoadContext survives the reload cycle.\n //\n // We must update the store directly (not via router.updateMatch) because\n // updateMatch wraps in startTransition which may defer the state update,\n // and we need the clear to be visible before invalidate reads the store.\n if (removedKeys.has('loader') || removedKeys.has('beforeLoad')) {\n const matchIds = [\n activeMatch?.id,\n pendingMatch?.id,\n ...cachedMatches.map((match) => match.id),\n ].filter(Boolean) as Array<string>\n router.batch(() => {\n for (const matchId of matchIds) {\n const store =\n router.stores.pendingMatchStores.get(matchId) ||\n router.stores.matchStores.get(matchId) ||\n router.stores.cachedMatchStores.get(matchId)\n if (store) {\n store.set((prev) => {\n const next: AnyRouteMatchWithPrivateProps = { ...prev }\n\n if (removedKeys.has('loader')) {\n next.loaderData = undefined\n }\n if (removedKeys.has('beforeLoad')) {\n next.__beforeLoadContext = undefined\n next.context = rebuildMatchContextWithoutBeforeLoad(next)\n }\n\n return next\n })\n }\n }\n })\n }\n\n router.invalidate({ filter, sync: true })\n }\n\n function walkReplaceSegmentTree(\n route: AnyRouteWithPrivateProps,\n node: AnyRouter['processedTree']['segmentTree'],\n ) {\n if (node.route?.id === route.id) node.route = route\n if (node.index) walkReplaceSegmentTree(route, node.index)\n node.static?.forEach((child) => walkReplaceSegmentTree(route, child))\n node.staticInsensitive?.forEach((child) =>\n walkReplaceSegmentTree(route, child),\n )\n node.dynamic?.forEach((child) => walkReplaceSegmentTree(route, child))\n node.optional?.forEach((child) => walkReplaceSegmentTree(route, child))\n node.wildcard?.forEach((child) => walkReplaceSegmentTree(route, child))\n }\n\n function getStoreMatch(matchId: string) {\n return (\n router.stores.pendingMatchStores.get(matchId)?.get() ||\n router.stores.matchStores.get(matchId)?.get() ||\n router.stores.cachedMatchStores.get(matchId)?.get()\n )\n }\n\n function getMatchList(matchId: string) {\n const pendingMatches = router.stores.pendingMatches.get()\n if (pendingMatches.some((match) => match.id === matchId)) {\n return pendingMatches\n }\n\n const activeMatches = router.stores.matches.get()\n if (activeMatches.some((match) => match.id === matchId)) {\n return activeMatches\n }\n\n const cachedMatches = router.stores.cachedMatches.get()\n if (cachedMatches.some((match) => match.id === matchId)) {\n return cachedMatches\n }\n\n return []\n }\n\n function getParentMatch(match: AnyRouteMatch) {\n const matchList = getMatchList(match.id)\n const matchIndex = matchList.findIndex((item) => item.id === match.id)\n\n if (matchIndex <= 0) {\n return undefined\n }\n\n const parentMatch = matchList[matchIndex - 1]!\n return getStoreMatch(parentMatch.id) || parentMatch\n }\n\n function rebuildMatchContextWithoutBeforeLoad(\n match: AnyRouteMatchWithPrivateProps,\n ) {\n const parentMatch = getParentMatch(match)\n const getParentContext = (\n router as unknown as {\n getParentContext?: (\n parentMatch?: AnyRouteMatch,\n ) => Record<string, unknown> | undefined\n }\n ).getParentContext\n const parentContext = getParentContext\n ? getParentContext.call(router, parentMatch)\n : (parentMatch?.context ?? router.options.context)\n\n return {\n ...(parentContext ?? {}),\n ...(match.__routeContext ?? {}),\n }\n }\n}\n\nconst handleRouteUpdateStr = handleRouteUpdate.toString()\n\nexport function getHandleRouteUpdateCode(stableRouteOptionKeys: Array<string>) {\n return handleRouteUpdateStr.replace(\n /['\"]__TSR_COMPONENT_TYPES__['\"]/,\n JSON.stringify(stableRouteOptionKeys),\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getHandleRouteUpdateCode(stableRouteOptionKeys: Array<string>): string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createRouteHmrStatement } from './select-adapter.cjs';
|
|
2
|
+
export type { CreateRouteHmrStatementOpts } from './select-adapter.cjs';
|
|
3
|
+
export { createViteHmrStatement } from './vite-adapter.cjs';
|
|
4
|
+
export { createWebpackHmrStatement } from './webpack-adapter.cjs';
|
|
5
|
+
export { getHandleRouteUpdateCode } from './handle-route-update.cjs';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const require_vite_adapter = require("./vite-adapter.cjs");
|
|
2
|
+
const require_webpack_adapter = require("./webpack-adapter.cjs");
|
|
3
|
+
//#region src/core/hmr/select-adapter.ts
|
|
4
|
+
/**
|
|
5
|
+
* Dispatches to the configured HMR adapter. `hmrStyle` is set explicitly by
|
|
6
|
+
* the bundler-specific plugin entry (e.g. `rspack.ts` → `'webpack'`), so there
|
|
7
|
+
* is no runtime inference based on config string shapes.
|
|
8
|
+
*/
|
|
9
|
+
function createRouteHmrStatement(stableRouteOptionKeys, opts) {
|
|
10
|
+
const routeId = opts.routeId === "/__root" ? "__root__" : opts.routeId;
|
|
11
|
+
if (opts.hmrStyle === "webpack") return require_webpack_adapter.createWebpackHmrStatement(stableRouteOptionKeys, {
|
|
12
|
+
targetFramework: opts.targetFramework,
|
|
13
|
+
routeId
|
|
14
|
+
});
|
|
15
|
+
return require_vite_adapter.createViteHmrStatement(stableRouteOptionKeys, { routeId });
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.createRouteHmrStatement = createRouteHmrStatement;
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=select-adapter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-adapter.cjs","names":[],"sources":["../../../../src/core/hmr/select-adapter.ts"],"sourcesContent":["import { createViteHmrStatement } from './vite-adapter'\nimport { createWebpackHmrStatement } from './webpack-adapter'\nimport type { Config, HmrStyle } from '../config'\nimport type * as t from '@babel/types'\n\nexport type CreateRouteHmrStatementOpts = {\n hmrStyle: HmrStyle\n targetFramework: Config['target']\n routeId?: string\n}\n\n/**\n * Dispatches to the configured HMR adapter. `hmrStyle` is set explicitly by\n * the bundler-specific plugin entry (e.g. `rspack.ts` → `'webpack'`), so there\n * is no runtime inference based on config string shapes.\n */\nexport function createRouteHmrStatement(\n stableRouteOptionKeys: Array<string>,\n opts: CreateRouteHmrStatementOpts,\n): Array<t.Statement> {\n const routeId = opts.routeId === '/__root' ? '__root__' : opts.routeId\n\n if (opts.hmrStyle === 'webpack') {\n return createWebpackHmrStatement(stableRouteOptionKeys, {\n targetFramework: opts.targetFramework,\n routeId,\n })\n }\n return createViteHmrStatement(stableRouteOptionKeys, {\n routeId,\n })\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,wBACd,uBACA,MACoB;CACpB,MAAM,UAAU,KAAK,YAAY,YAAY,aAAa,KAAK;AAE/D,KAAI,KAAK,aAAa,UACpB,QAAO,wBAAA,0BAA0B,uBAAuB;EACtD,iBAAiB,KAAK;EACtB;EACD,CAAC;AAEJ,QAAO,qBAAA,uBAAuB,uBAAuB,EACnD,SACD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Config, HmrStyle } from '../config.cjs';
|
|
2
|
+
import type * as t from '@babel/types';
|
|
3
|
+
export type CreateRouteHmrStatementOpts = {
|
|
4
|
+
hmrStyle: HmrStyle;
|
|
5
|
+
targetFramework: Config['target'];
|
|
6
|
+
routeId?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Dispatches to the configured HMR adapter. `hmrStyle` is set explicitly by
|
|
10
|
+
* the bundler-specific plugin entry (e.g. `rspack.ts` → `'webpack'`), so there
|
|
11
|
+
* is no runtime inference based on config string shapes.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createRouteHmrStatement(stableRouteOptionKeys: Array<string>, opts: CreateRouteHmrStatementOpts): Array<t.Statement>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_handle_route_update = require("./handle-route-update.cjs");
|
|
3
|
+
let _babel_template = require("@babel/template");
|
|
4
|
+
_babel_template = require_runtime.__toESM(_babel_template);
|
|
5
|
+
//#region src/core/hmr/vite-adapter.ts
|
|
6
|
+
/**
|
|
7
|
+
* Emits HMR accept code for Vite / native ESM HMR: `import.meta.hot.accept`
|
|
8
|
+
* with a callback that receives the freshly re-imported module.
|
|
9
|
+
*
|
|
10
|
+
* `targetFramework` is currently unused — Vite's framework-specific fast-refresh
|
|
11
|
+
* plugins handle component body patching via their own accept boundaries — but
|
|
12
|
+
* we take it for API symmetry with `createWebpackHmrStatement`.
|
|
13
|
+
*/
|
|
14
|
+
function createViteHmrStatement(stableRouteOptionKeys, opts = {}) {
|
|
15
|
+
const handleRouteUpdateCode = require_handle_route_update.getHandleRouteUpdateCode(stableRouteOptionKeys);
|
|
16
|
+
const routeIdFallback = typeof opts.routeId === "string" ? JSON.stringify(opts.routeId) : "Route.id";
|
|
17
|
+
return [_babel_template.statement(`
|
|
18
|
+
if (import.meta.hot) {
|
|
19
|
+
const hot = import.meta.hot
|
|
20
|
+
const hotData = hot.data ??= {}
|
|
21
|
+
hot.accept((newModule) => {
|
|
22
|
+
if (Route && newModule && newModule.Route) {
|
|
23
|
+
const routeId = hotData['tsr-route-id'] ?? ${routeIdFallback}
|
|
24
|
+
if (routeId) {
|
|
25
|
+
hotData['tsr-route-id'] = routeId
|
|
26
|
+
}
|
|
27
|
+
(${handleRouteUpdateCode})(routeId, newModule.Route)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
`, { syntacticPlaceholders: true })()];
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
exports.createViteHmrStatement = createViteHmrStatement;
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=vite-adapter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-adapter.cjs","names":[],"sources":["../../../../src/core/hmr/vite-adapter.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport { getHandleRouteUpdateCode } from './handle-route-update'\nimport type * as t from '@babel/types'\n\n/**\n * Emits HMR accept code for Vite / native ESM HMR: `import.meta.hot.accept`\n * with a callback that receives the freshly re-imported module.\n *\n * `targetFramework` is currently unused — Vite's framework-specific fast-refresh\n * plugins handle component body patching via their own accept boundaries — but\n * we take it for API symmetry with `createWebpackHmrStatement`.\n */\nexport function createViteHmrStatement(\n stableRouteOptionKeys: Array<string>,\n opts: {\n routeId?: string\n } = {},\n): Array<t.Statement> {\n const handleRouteUpdateCode = getHandleRouteUpdateCode(stableRouteOptionKeys)\n // The replacement Route object can be uninitialized; keep a generated id as\n // fallback for the existing router route we need to patch.\n const routeIdFallback =\n typeof opts.routeId === 'string' ? JSON.stringify(opts.routeId) : 'Route.id'\n\n return [\n template.statement(\n `\nif (import.meta.hot) {\n const hot = import.meta.hot\n const hotData = hot.data ??= {}\n hot.accept((newModule) => {\n if (Route && newModule && newModule.Route) {\n const routeId = hotData['tsr-route-id'] ?? ${routeIdFallback}\n if (routeId) {\n hotData['tsr-route-id'] = routeId\n }\n (${handleRouteUpdateCode})(routeId, newModule.Route)\n }\n })\n}\n`,\n {\n syntacticPlaceholders: true,\n },\n )(),\n ]\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,uBACd,uBACA,OAEI,EAAE,EACc;CACpB,MAAM,wBAAwB,4BAAA,yBAAyB,sBAAsB;CAG7E,MAAM,kBACJ,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,KAAK,QAAQ,GAAG;AAEpE,QAAO,CACL,gBAAS,UACP;;;;;;mDAM6C,gBAAgB;;;;SAI1D,sBAAsB;;;;GAKzB,EACE,uBAAuB,MACxB,CACF,EAAE,CACJ"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type * as t from '@babel/types';
|
|
2
|
+
/**
|
|
3
|
+
* Emits HMR accept code for Vite / native ESM HMR: `import.meta.hot.accept`
|
|
4
|
+
* with a callback that receives the freshly re-imported module.
|
|
5
|
+
*
|
|
6
|
+
* `targetFramework` is currently unused — Vite's framework-specific fast-refresh
|
|
7
|
+
* plugins handle component body patching via their own accept boundaries — but
|
|
8
|
+
* we take it for API symmetry with `createWebpackHmrStatement`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createViteHmrStatement(stableRouteOptionKeys: Array<string>, opts?: {
|
|
11
|
+
routeId?: string;
|
|
12
|
+
}): Array<t.Statement>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_handle_route_update = require("./handle-route-update.cjs");
|
|
3
|
+
let _babel_template = require("@babel/template");
|
|
4
|
+
_babel_template = require_runtime.__toESM(_babel_template);
|
|
5
|
+
//#region src/core/hmr/webpack-adapter.ts
|
|
6
|
+
/**
|
|
7
|
+
* Emits HMR accept code for bundlers with webpack-compatible `module.hot`
|
|
8
|
+
* semantics (classic webpack via `import.meta.webpackHot`, and Rspack).
|
|
9
|
+
*
|
|
10
|
+
* Unlike Vite's `hot.accept((newModule) => {...})` — where the callback receives
|
|
11
|
+
* the freshly re-imported module — webpack re-executes the module factory on
|
|
12
|
+
* accept, so our HMR logic must live at module top level and read the previous
|
|
13
|
+
* `routeId` out of `hot.data`. `hot.dispose` stashes it for the next run, and
|
|
14
|
+
* `hot.accept()` (no callback) enrolls us as a self-accepting boundary.
|
|
15
|
+
*
|
|
16
|
+
* Returns an array of statements so that for React we can prepend an
|
|
17
|
+
* `import { performReactRefresh } from 'react-refresh/runtime'` hoisted to the
|
|
18
|
+
* top of the module.
|
|
19
|
+
*/
|
|
20
|
+
function createWebpackHmrStatement(stableRouteOptionKeys, opts) {
|
|
21
|
+
const handleRouteUpdateCode = require_handle_route_update.getHandleRouteUpdateCode(stableRouteOptionKeys);
|
|
22
|
+
const staticRouteIdLiteral = typeof opts.routeId === "string" ? JSON.stringify(opts.routeId) : "undefined";
|
|
23
|
+
const statements = [];
|
|
24
|
+
const reactRefreshCall = opts.targetFramework === "react" ? `
|
|
25
|
+
const tsrRefreshState = globalThis.__TSR_HMR__ ??= {}
|
|
26
|
+
try {
|
|
27
|
+
if (!tsrRefreshState.refreshScheduled) {
|
|
28
|
+
tsrRefreshState.refreshScheduled = true
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
tsrRefreshState.refreshScheduled = false
|
|
31
|
+
try { __tsr_performReactRefresh() } catch (_e) { /* noop */ }
|
|
32
|
+
}, 30)
|
|
33
|
+
}
|
|
34
|
+
} catch (_err) { /* noop */ }` : "";
|
|
35
|
+
if (opts.targetFramework === "react") statements.push(_babel_template.statement(`import { performReactRefresh as __tsr_performReactRefresh } from 'react-refresh/runtime'`)());
|
|
36
|
+
statements.push(_babel_template.statement(`
|
|
37
|
+
if (import.meta.webpackHot) {
|
|
38
|
+
const hot = import.meta.webpackHot
|
|
39
|
+
const hotData = hot.data ??= {}
|
|
40
|
+
const routeId = hotData['tsr-route-id'] ?? Route.id ?? (Route.isRoot ? '__root__' : ${staticRouteIdLiteral})
|
|
41
|
+
if (routeId) {
|
|
42
|
+
hotData['tsr-route-id'] = routeId
|
|
43
|
+
}
|
|
44
|
+
const existingRoute =
|
|
45
|
+
typeof window !== 'undefined' && routeId
|
|
46
|
+
? window.__TSR_ROUTER__?.routesById?.[routeId]
|
|
47
|
+
: undefined
|
|
48
|
+
if (routeId && existingRoute && existingRoute !== Route) {
|
|
49
|
+
(${handleRouteUpdateCode})(routeId, Route)${reactRefreshCall}
|
|
50
|
+
}
|
|
51
|
+
hot.dispose((data) => {
|
|
52
|
+
if (routeId) {
|
|
53
|
+
data['tsr-route-id'] = routeId
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
hot.accept()
|
|
57
|
+
}
|
|
58
|
+
`, { syntacticPlaceholders: true })());
|
|
59
|
+
return statements;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
exports.createWebpackHmrStatement = createWebpackHmrStatement;
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=webpack-adapter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webpack-adapter.cjs","names":[],"sources":["../../../../src/core/hmr/webpack-adapter.ts"],"sourcesContent":["import * as template from '@babel/template'\nimport { getHandleRouteUpdateCode } from './handle-route-update'\nimport type { Config } from '../config'\nimport type * as t from '@babel/types'\n\n/**\n * Emits HMR accept code for bundlers with webpack-compatible `module.hot`\n * semantics (classic webpack via `import.meta.webpackHot`, and Rspack).\n *\n * Unlike Vite's `hot.accept((newModule) => {...})` — where the callback receives\n * the freshly re-imported module — webpack re-executes the module factory on\n * accept, so our HMR logic must live at module top level and read the previous\n * `routeId` out of `hot.data`. `hot.dispose` stashes it for the next run, and\n * `hot.accept()` (no callback) enrolls us as a self-accepting boundary.\n *\n * Returns an array of statements so that for React we can prepend an\n * `import { performReactRefresh } from 'react-refresh/runtime'` hoisted to the\n * top of the module.\n */\nexport function createWebpackHmrStatement(\n stableRouteOptionKeys: Array<string>,\n opts: {\n targetFramework: Config['target']\n routeId?: string\n },\n): Array<t.Statement> {\n const handleRouteUpdateCode = getHandleRouteUpdateCode(stableRouteOptionKeys)\n const staticRouteIdLiteral =\n typeof opts.routeId === 'string'\n ? JSON.stringify(opts.routeId)\n : 'undefined'\n\n const statements: Array<t.Statement> = []\n\n // React-only: route modules aren't React Refresh \"boundaries\" (they export\n // a non-component `Route`), so the bundler's react-refresh runtime won't\n // call `performReactRefresh` for us. We kick it manually after swapping\n // route options so newly-registered component bodies get patched into live\n // fibers.\n //\n // We import `performReactRefresh` directly from `react-refresh/runtime` —\n // the canonical public API — rather than relying on the ProvidePlugin-\n // injected `__react_refresh_utils__` global, whose name is an internal\n // detail of `@rspack/plugin-react-refresh`. The rspack plugin aliases\n // `react-refresh` → its bundled runtime (getRefreshRuntimeDirPath), so this\n // resolves to the same singleton the plugin itself uses and shares the\n // registry React was patched against.\n //\n // Use the same delayed refresh style as Rspack's React Refresh runtime.\n // Route modules and their split component chunks can arrive in separate HMR\n // steps under CI load; a microtask can run before the split chunk registers\n // its new component family, causing the refresh to no-op or remount.\n //\n // For non-React frameworks we skip this entirely.\n const reactRefreshCall =\n opts.targetFramework === 'react'\n ? `\n const tsrRefreshState = globalThis.__TSR_HMR__ ??= {}\n try {\n if (!tsrRefreshState.refreshScheduled) {\n tsrRefreshState.refreshScheduled = true\n setTimeout(() => {\n tsrRefreshState.refreshScheduled = false\n try { __tsr_performReactRefresh() } catch (_e) { /* noop */ }\n }, 30)\n }\n } catch (_err) { /* noop */ }`\n : ''\n\n if (opts.targetFramework === 'react') {\n statements.push(\n template.statement(\n `import { performReactRefresh as __tsr_performReactRefresh } from 'react-refresh/runtime'`,\n )(),\n )\n }\n\n statements.push(\n template.statement(\n `\nif (import.meta.webpackHot) {\n const hot = import.meta.webpackHot\n const hotData = hot.data ??= {}\n const routeId = hotData['tsr-route-id'] ?? Route.id ?? (Route.isRoot ? '__root__' : ${staticRouteIdLiteral})\n if (routeId) {\n hotData['tsr-route-id'] = routeId\n }\n const existingRoute =\n typeof window !== 'undefined' && routeId\n ? window.__TSR_ROUTER__?.routesById?.[routeId]\n : undefined\n if (routeId && existingRoute && existingRoute !== Route) {\n (${handleRouteUpdateCode})(routeId, Route)${reactRefreshCall}\n }\n hot.dispose((data) => {\n if (routeId) {\n data['tsr-route-id'] = routeId\n }\n })\n hot.accept()\n}\n`,\n {\n syntacticPlaceholders: true,\n },\n )(),\n )\n\n return statements\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,0BACd,uBACA,MAIoB;CACpB,MAAM,wBAAwB,4BAAA,yBAAyB,sBAAsB;CAC7E,MAAM,uBACJ,OAAO,KAAK,YAAY,WACpB,KAAK,UAAU,KAAK,QAAQ,GAC5B;CAEN,MAAM,aAAiC,EAAE;CAsBzC,MAAM,mBACJ,KAAK,oBAAoB,UACrB;;;;;;;;;;qCAWA;AAEN,KAAI,KAAK,oBAAoB,QAC3B,YAAW,KACT,gBAAS,UACP,2FACD,EAAE,CACJ;AAGH,YAAW,KACT,gBAAS,UACP;;;;wFAIkF,qBAAqB;;;;;;;;;OAStG,sBAAsB,mBAAmB,iBAAiB;;;;;;;;;GAU3D,EACE,uBAAuB,MACxB,CACF,EAAE,CACJ;AAED,QAAO"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Config } from '../config.cjs';
|
|
2
|
+
import type * as t from '@babel/types';
|
|
3
|
+
/**
|
|
4
|
+
* Emits HMR accept code for bundlers with webpack-compatible `module.hot`
|
|
5
|
+
* semantics (classic webpack via `import.meta.webpackHot`, and Rspack).
|
|
6
|
+
*
|
|
7
|
+
* Unlike Vite's `hot.accept((newModule) => {...})` — where the callback receives
|
|
8
|
+
* the freshly re-imported module — webpack re-executes the module factory on
|
|
9
|
+
* accept, so our HMR logic must live at module top level and read the previous
|
|
10
|
+
* `routeId` out of `hot.data`. `hot.dispose` stashes it for the next run, and
|
|
11
|
+
* `hot.accept()` (no callback) enrolls us as a self-accepting boundary.
|
|
12
|
+
*
|
|
13
|
+
* Returns an array of statements so that for React we can prepend an
|
|
14
|
+
* `import { performReactRefresh } from 'react-refresh/runtime'` hoisted to the
|
|
15
|
+
* top of the module.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createWebpackHmrStatement(stableRouteOptionKeys: Array<string>, opts: {
|
|
18
|
+
targetFramework: Config['target'];
|
|
19
|
+
routeId?: string;
|
|
20
|
+
}): Array<t.Statement>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
const require_config = require("./config.cjs");
|
|
3
|
-
const require_hmr_hot_expression = require("./hmr-hot-expression.cjs");
|
|
4
3
|
const require_constants = require("./constants.cjs");
|
|
5
4
|
const require_utils = require("./utils.cjs");
|
|
6
5
|
const require_path_ids = require("./code-splitter/path-ids.cjs");
|
|
@@ -67,7 +66,7 @@ var unpluginRouterCodeSplitterFactory = (options = {}, { framework: _framework }
|
|
|
67
66
|
throw new Error(`The groupings for the route "${id}" are invalid.\n${message}`);
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
|
-
const pluginSplitBehavior = getShouldSplitFn()?.({ routeId: generatorNodeInfo.
|
|
69
|
+
const pluginSplitBehavior = getShouldSplitFn()?.({ routeId: generatorNodeInfo.routeId });
|
|
71
70
|
if (pluginSplitBehavior) {
|
|
72
71
|
const res = require_config.splitGroupingsSchema.safeParse(pluginSplitBehavior);
|
|
73
72
|
if (!res.success) {
|
|
@@ -83,7 +82,7 @@ var unpluginRouterCodeSplitterFactory = (options = {}, { framework: _framework }
|
|
|
83
82
|
if (sharedBindings.size > 0) sharedBindingsMap.set(id, sharedBindings);
|
|
84
83
|
else sharedBindingsMap.delete(id);
|
|
85
84
|
const addHmr = (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction;
|
|
86
|
-
const
|
|
85
|
+
const hmrStyle = userConfig.plugin?.hmr?.style ?? "vite";
|
|
87
86
|
const compiledReferenceRoute = require_compilers.compileCodeSplitReferenceRoute({
|
|
88
87
|
code,
|
|
89
88
|
codeSplitGroupings: splitGroupings,
|
|
@@ -92,12 +91,13 @@ var unpluginRouterCodeSplitterFactory = (options = {}, { framework: _framework }
|
|
|
92
91
|
id,
|
|
93
92
|
deleteNodes: userConfig.codeSplittingOptions?.deleteNodes ? new Set(userConfig.codeSplittingOptions.deleteNodes) : void 0,
|
|
94
93
|
addHmr,
|
|
95
|
-
|
|
94
|
+
hmrStyle,
|
|
95
|
+
hmrRouteId: generatorNodeInfo.routeId,
|
|
96
96
|
sharedBindings: sharedBindings.size > 0 ? sharedBindings : void 0,
|
|
97
97
|
compilerPlugins: require_framework_plugins.getReferenceRouteCompilerPlugins({
|
|
98
98
|
targetFramework: userConfig.target,
|
|
99
99
|
addHmr,
|
|
100
|
-
|
|
100
|
+
hmrStyle
|
|
101
101
|
})
|
|
102
102
|
});
|
|
103
103
|
if (compiledReferenceRoute === null) {
|