@reckona/mreact-router 0.0.194 → 0.0.196

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/src/client.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readFile, stat } from "node:fs/promises";
3
3
  import { builtinModules } from "node:module";
4
- import { dirname, extname, join, relative, sep } from "node:path";
4
+ import { basename, dirname, extname, isAbsolute, join, relative, sep } from "node:path";
5
5
  import {
6
6
  analyzeBoundaryGraph,
7
7
  collectClientRouteModuleAnalysis,
@@ -68,6 +68,7 @@ export interface ClientRouteManifestEntry {
68
68
  export interface BuildClientRouteOutputOptions {
69
69
  cacheDir?: string | undefined;
70
70
  code: string;
71
+ debugLabels?: boolean | undefined;
71
72
  clientBoundaryImports?: readonly string[] | undefined;
72
73
  clientReferenceImports?: readonly ClientReferenceImport[] | undefined;
73
74
  clientReferenceManifest?: readonly ClientReferenceMetadata[] | undefined;
@@ -2104,6 +2105,13 @@ export async function buildClientRouteOutput(
2104
2105
  const entry = await buildClientRouteEntrySource(options);
2105
2106
  const dropConsoleFunctions =
2106
2107
  options.dropConsoleFunctions ?? resolveClientConsolePureFunctions(options.dropClientConsole);
2108
+ const sourceRegionModulePaths =
2109
+ options.debugLabels === true ? undefined : new Set([options.filename]);
2110
+ const runtimePlugin = workspaceRuntimePlugin({
2111
+ debugLabels: options.debugLabels === true,
2112
+ routeFiles: [options.filename],
2113
+ sourceRegionModulePaths,
2114
+ });
2107
2115
  const bundled = await bundleRouterModule({
2108
2116
  code: entry.code,
2109
2117
  cacheDir: options.cacheDir,
@@ -2115,7 +2123,8 @@ export async function buildClientRouteOutput(
2115
2123
  minify: options.minify === true,
2116
2124
  platform: "browser",
2117
2125
  preserveExports: true,
2118
- plugins: [workspaceRuntimePlugin({ routeFiles: [options.filename] })],
2126
+ sourceRegionModulePaths,
2127
+ plugins: [runtimePlugin],
2119
2128
  sourceMap: options.sourceMap,
2120
2129
  vitePlugins: options.vitePlugins,
2121
2130
  });
@@ -2149,6 +2158,15 @@ export async function buildClientRouteBatchOutput(options: {
2149
2158
  }),
2150
2159
  })),
2151
2160
  );
2161
+ const debugLabels = options.routes.some((route) => route.debugLabels === true);
2162
+ const sourceRegionModulePaths = debugLabels
2163
+ ? undefined
2164
+ : new Set(entries.map((entry) => entry.filename));
2165
+ const runtimePlugin = workspaceRuntimePlugin({
2166
+ debugLabels,
2167
+ routeFiles: entries.map((entry) => entry.filename),
2168
+ sourceRegionModulePaths,
2169
+ });
2152
2170
  const bundled = await bundleRouterModules({
2153
2171
  base: options.assetBaseUrl ?? "/_mreact/client/",
2154
2172
  cacheDir: options.cacheDir,
@@ -2162,7 +2180,8 @@ export async function buildClientRouteBatchOutput(options: {
2162
2180
  })),
2163
2181
  minify: options.minify === true,
2164
2182
  platform: "browser",
2165
- plugins: [workspaceRuntimePlugin({ routeFiles: entries.map((entry) => entry.filename) })],
2183
+ sourceRegionModulePaths,
2184
+ plugins: [runtimePlugin],
2166
2185
  root: options.projectRoot,
2167
2186
  sourceMap: options.sourceMap,
2168
2187
  dropConsoleFunctions: options.dropConsoleFunctions,
@@ -2199,13 +2218,22 @@ export async function buildClientRouteEntrySource(
2199
2218
  filename: options.filename,
2200
2219
  });
2201
2220
  const routeSourceAnalysis = collectClientRouteModuleAnalysisFromContext(moduleContext);
2221
+ const compilerFilename =
2222
+ options.debugLabels === true ? basename(options.filename) : options.filename;
2223
+ const compilerModuleContext =
2224
+ compilerFilename === options.filename
2225
+ ? moduleContext
2226
+ : createCompilerModuleContext({
2227
+ code: options.code,
2228
+ filename: compilerFilename,
2229
+ });
2202
2230
  const compiled = transformCompilerModuleContext({
2203
2231
  code: options.code,
2204
2232
  clientBoundaryImports: options.clientBoundaryImports ?? [],
2205
- filename: options.filename,
2206
- moduleContext,
2233
+ filename: compilerFilename,
2234
+ moduleContext: compilerModuleContext,
2207
2235
  target: "client",
2208
- dev: options.minify !== true,
2236
+ dev: options.debugLabels === true,
2209
2237
  });
2210
2238
 
2211
2239
  if (compiled.diagnostics.length > 0) {
@@ -2238,7 +2266,12 @@ export async function buildClientRouteEntrySource(
2238
2266
  const routeId = routeIdForPath(options.routePath);
2239
2267
  const routeUsesCells = detectRouteCellStateHint(compiled.code);
2240
2268
  const routeUsesReactiveEffect = detectRouteReactiveEffectHint(compiled.code);
2241
- const routeUsesCleanupScope = routeUsesCells || routeUsesReactiveEffect;
2269
+ const routeUsesDomRefs = compiled.metadata.imports.some(
2270
+ (entry) =>
2271
+ entry.source === "@reckona/mreact-reactive-dom" &&
2272
+ entry.specifiers.includes("bindDomRef"),
2273
+ );
2274
+ const routeUsesCleanupScope = routeUsesCells || routeUsesReactiveEffect || routeUsesDomRefs;
2242
2275
  const routeExplicitlyRequiresHydration = isExplicitClientRouteSource(
2243
2276
  routeSourceAnalysis,
2244
2277
  options.filename,
@@ -2254,6 +2287,7 @@ export async function buildClientRouteEntrySource(
2254
2287
  routeExplicitlyRequiresHydration ||
2255
2288
  routeUsesCells ||
2256
2289
  routeUsesReactiveEffect ||
2290
+ routeUsesDomRefs ||
2257
2291
  routeHasEventBindings;
2258
2292
  const routeUsesOnlyClientReferenceBoundaries =
2259
2293
  !routeRequiresFullHydration &&
@@ -2276,7 +2310,7 @@ export async function buildClientRouteEntrySource(
2276
2310
  ? `import { bindCapturedEvent as __mreactBindCapturedEvent } from "@reckona/mreact-reactive-dom/internal";\n`
2277
2311
  : "";
2278
2312
  const routeReactiveDomMetadataImport = !routeUsesOnlyClientReferenceBoundaries
2279
- ? `${routeCapturedEventImport}import { withEventBindingMetadata as __mreactWithEventBindingMetadata, withPropBindingMetadata as __mreactWithPropBindingMetadata } from "@reckona/mreact-reactive-dom";\n`
2313
+ ? `${routeCapturedEventImport}import { ${routeUsesDomRefs ? "getDomRefBindings as __mreactGetDomRefBindings, " : ""}withEventBindingMetadata as __mreactWithEventBindingMetadata, withPropBindingMetadata as __mreactWithPropBindingMetadata } from "@reckona/mreact-reactive-dom";\n`
2280
2314
  : "";
2281
2315
  const navigationStateDeclaration = inlineClientNavigation
2282
2316
  ? `const __mreactNavigationState = __mreactGlobal.__mreactNavigationState ??= {
@@ -2552,9 +2586,10 @@ __mreactGlobal.__mreactRouteCell = (nativeCell, initial) => {
2552
2586
  __mreactActiveCellIndex = 0;
2553
2587
  }
2554
2588
  return () => {
2555
- for (const __mreactDispose of Array.from(__mreactRouteEffectDisposers)) {
2556
- __mreactDispose();
2557
- }
2589
+ __mreactRunLifecycleTasks(
2590
+ Array.from(__mreactRouteEffectDisposers),
2591
+ (__mreactDispose) => __mreactDispose(),
2592
+ );
2558
2593
  __mreactRouteEffectDisposers.clear();
2559
2594
  };
2560
2595
  });
@@ -2566,13 +2601,33 @@ __mreactGlobal.__mreactRouteCell = (nativeCell, initial) => {
2566
2601
  ? ` __mreactDisposeRoute(__mreactRouteId);
2567
2602
  const __mreactRouteEffectDisposers = new Set();
2568
2603
  __mreactRouteDisposers.set(__mreactRouteId, () => {
2569
- for (const __mreactDispose of Array.from(__mreactRouteEffectDisposers)) {
2570
- __mreactDispose();
2571
- }
2604
+ __mreactRunLifecycleTasks(
2605
+ Array.from(__mreactRouteEffectDisposers),
2606
+ (__mreactDispose) => __mreactDispose(),
2607
+ );
2572
2608
  __mreactRouteEffectDisposers.clear();
2573
2609
  });
2574
2610
  `
2575
2611
  : "";
2612
+ const routeLifecycleFunctions = `
2613
+ function __mreactRunLifecycleTasks(values, run) {
2614
+ let firstError;
2615
+
2616
+ for (const value of values) {
2617
+ try {
2618
+ run(value);
2619
+ } catch (error) {
2620
+ firstError ??= error;
2621
+ }
2622
+ }
2623
+
2624
+ if (firstError !== undefined) {
2625
+ queueMicrotask(() => {
2626
+ throw firstError;
2627
+ });
2628
+ }
2629
+ }
2630
+ `;
2576
2631
  const routeCellDropFunction = routeUsesCells
2577
2632
  ? `
2578
2633
  function __mreactDropMismatchedRouteState(previousState, nextState) {
@@ -2598,12 +2653,18 @@ function __mreactDisposeRoute(routeId) {
2598
2653
  }
2599
2654
  `
2600
2655
  : "";
2601
- const routeCleanupNavigationDispose = routeUsesCleanupScope
2602
- ? ` if (currentRouteId !== nextRouteId) {
2603
- __mreactDisposeRoute(currentRouteId);
2656
+ const routeCleanupNavigationDispose = ` if (currentRouteId !== nextRouteId) {
2657
+ const __mreactRegisteredRouteDisposers = __mreactGlobal.__mreactRouteDisposers;
2658
+ const __mreactRegisteredRouteDispose = __mreactRegisteredRouteDisposers?.get(currentRouteId);
2659
+ if (__mreactRegisteredRouteDispose !== undefined) {
2660
+ __mreactRegisteredRouteDisposers.delete(currentRouteId);
2661
+ __mreactRunLifecycleTasks(
2662
+ [__mreactRegisteredRouteDispose],
2663
+ (__mreactDispose) => __mreactDispose(),
2664
+ );
2665
+ }
2604
2666
  }
2605
- `
2606
- : "";
2667
+ `;
2607
2668
  const routeNodeResolver = routeUsesCells
2608
2669
  ? `
2609
2670
  function __mreactResolveRouteNode(value) {
@@ -2642,9 +2703,7 @@ function __mreactResolveRouteNode(value) {
2642
2703
  const previousDisposers = current.__mreactEventDisposers;
2643
2704
 
2644
2705
  if (Array.isArray(previousDisposers)) {
2645
- for (const dispose of previousDisposers) {
2646
- dispose();
2647
- }
2706
+ __mreactRunLifecycleTasks(previousDisposers, (dispose) => dispose());
2648
2707
  }
2649
2708
 
2650
2709
  const rawBindings = next.__mreactEventBindings;
@@ -2673,14 +2732,26 @@ function __mreactResolveRouteNode(value) {
2673
2732
  const previousDisposers = current.__mreactEventDisposers;
2674
2733
 
2675
2734
  if (Array.isArray(previousDisposers)) {
2676
- for (const dispose of previousDisposers) {
2677
- dispose();
2678
- }
2735
+ __mreactRunLifecycleTasks(previousDisposers, (dispose) => dispose());
2679
2736
  }
2680
2737
 
2681
2738
  current.__mreactEventDisposers = [];
2682
2739
  current.__mreactHasEvents = false;
2683
2740
  }
2741
+ `;
2742
+ const routeDomRefBindingSyncFunction = routeUsesDomRefs
2743
+ ? `function __mreactSyncDomRefBindings(current, next) {
2744
+ __mreactRunLifecycleTasks(
2745
+ Array.from(__mreactGetDomRefBindings(current)),
2746
+ (binding) => binding.dispose(),
2747
+ );
2748
+ __mreactRunLifecycleTasks(
2749
+ Array.from(__mreactGetDomRefBindings(next)),
2750
+ (binding) => binding.retarget(current),
2751
+ );
2752
+ }
2753
+ `
2754
+ : `function __mreactSyncDomRefBindings() {}
2684
2755
  `;
2685
2756
  const boundaryOnlyHydrationBlock = routeRequiresFullHydration
2686
2757
  ? ""
@@ -2740,6 +2811,7 @@ ${routeCellHydrationIndent}__mreactMarker.setAttribute(__mreactRouteHydratedAttr
2740
2811
  ${routeCellHydrationIndent}__mreactMarkRouteHydrated();
2741
2812
  ${routeCellHydrationEnd}}
2742
2813
  ${routeCellDropFunction}
2814
+ ${routeLifecycleFunctions}
2743
2815
  ${routeCleanupFunction}
2744
2816
 
2745
2817
  function __mreactMarkRouteHydrated() {
@@ -3327,13 +3399,14 @@ function __mreactApplyNavigationHtml(html, url) {
3327
3399
  const currentRouteId = currentMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
3328
3400
  const nextRouteId = nextMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
3329
3401
 
3402
+ ${routeCleanupNavigationDispose}
3330
3403
  __mreactMarkRouteHydrating();
3331
3404
  __mreactSyncHeadMetadata(template.content, html);
3332
3405
  if (!__mreactApplyNavigationShellHtml(currentMarker, nextMarker)) {
3333
3406
  __mreactUnmountCompatBoundaries(currentMarker);
3334
3407
  __mreactResumeNode(currentMarker, nextMarker);
3335
3408
  }
3336
- ${routeCleanupNavigationDispose} __mreactSyncRouteDataScripts(template.content, currentRouteId, nextRouteId);
3409
+ __mreactSyncRouteDataScripts(template.content, currentRouteId, nextRouteId);
3337
3410
 
3338
3411
  const script = template.content.querySelector('script[type="module"][src]')?.getAttribute("src");
3339
3412
  if (script !== null && script !== undefined) {
@@ -4150,13 +4223,15 @@ function __mreactHydrateClientBoundaries(marker, references, components) {
4150
4223
  return false;
4151
4224
  }
4152
4225
 
4153
- const placeholders = Array.from(marker.querySelectorAll("template[data-mreact-client-boundary]"));
4226
+ let hydrated = false;
4154
4227
 
4155
- if (placeholders.length === 0) {
4156
- return false;
4157
- }
4228
+ while (true) {
4229
+ const placeholder = marker.querySelector("template[data-mreact-client-boundary]");
4230
+
4231
+ if (placeholder === null) {
4232
+ return hydrated;
4233
+ }
4158
4234
 
4159
- for (const placeholder of placeholders) {
4160
4235
  const name = placeholder.getAttribute("data-mreact-client-boundary");
4161
4236
  const entry = name === null ? undefined : components.get(name);
4162
4237
  const component = typeof entry === "function" ? entry : entry?.component;
@@ -4190,6 +4265,7 @@ function __mreactHydrateClientBoundaries(marker, references, components) {
4190
4265
  const root = __mreactCompatCreateRoot(container);
4191
4266
  container.__mreactCompatRoot = root;
4192
4267
  root.render(__mreactCompatCreateElement(component, props));
4268
+ hydrated = true;
4193
4269
  continue;
4194
4270
  }
4195
4271
 
@@ -4197,9 +4273,8 @@ function __mreactHydrateClientBoundaries(marker, references, components) {
4197
4273
 
4198
4274
  placeholder.replaceWith(node);
4199
4275
  propsElement?.remove();
4276
+ hydrated = true;
4200
4277
  }
4201
-
4202
- return true;
4203
4278
  }
4204
4279
 
4205
4280
  function __mreactClientBoundaryParentContainer(placeholder, propsElement) {
@@ -4276,6 +4351,8 @@ function __mreactClientBoundaryPropsElement(placeholder, name) {
4276
4351
  }
4277
4352
 
4278
4353
  function __mreactClientBoundaryFallbackChildren(placeholder, propsElement) {
4354
+ const componentFallback =
4355
+ placeholder.getAttribute("data-mreact-client-boundary-fallback") === "component";
4279
4356
  const nodes = [];
4280
4357
  let next = placeholder.nextSibling;
4281
4358
 
@@ -4292,6 +4369,13 @@ function __mreactClientBoundaryFallbackChildren(placeholder, propsElement) {
4292
4369
  nodes.push(current);
4293
4370
  }
4294
4371
 
4372
+ if (componentFallback) {
4373
+ return __mreactExtractClientBoundaryChildren(
4374
+ nodes,
4375
+ placeholder.getAttribute("data-mreact-client-boundary"),
4376
+ );
4377
+ }
4378
+
4295
4379
  if (nodes.length === 0) {
4296
4380
  return undefined;
4297
4381
  }
@@ -4299,6 +4383,80 @@ function __mreactClientBoundaryFallbackChildren(placeholder, propsElement) {
4299
4383
  return nodes.length === 1 ? nodes[0] : nodes;
4300
4384
  }
4301
4385
 
4386
+ function __mreactExtractClientBoundaryChildren(nodes, name) {
4387
+ const startMarker = "mreact-client-boundary-children-start";
4388
+ const endMarker = "mreact-client-boundary-children-end";
4389
+ const archive = nodes.find(
4390
+ (node) =>
4391
+ node.nodeType === Node.ELEMENT_NODE &&
4392
+ node.tagName === "TEMPLATE" &&
4393
+ node.getAttribute("data-mreact-client-boundary-children") === name,
4394
+ );
4395
+
4396
+ const roots = archive === undefined ? nodes : Array.from(archive.content.childNodes);
4397
+ const markers = [];
4398
+ const visit = (node) => {
4399
+ if (
4400
+ node.nodeType === Node.COMMENT_NODE &&
4401
+ (node.nodeValue === startMarker || node.nodeValue === endMarker)
4402
+ ) {
4403
+ markers.push(node);
4404
+ }
4405
+
4406
+ for (const child of Array.from(node.childNodes ?? [])) {
4407
+ visit(child);
4408
+ }
4409
+ };
4410
+
4411
+ for (const root of roots) {
4412
+ visit(root);
4413
+ }
4414
+
4415
+ let start;
4416
+ let depth = 0;
4417
+
4418
+ for (const marker of markers) {
4419
+ if (marker.nodeValue === startMarker) {
4420
+ if (depth === 0) {
4421
+ start = marker;
4422
+ }
4423
+ depth += 1;
4424
+ continue;
4425
+ }
4426
+
4427
+ if (depth === 0 || start === undefined) {
4428
+ continue;
4429
+ }
4430
+
4431
+ depth -= 1;
4432
+
4433
+ if (depth !== 0) {
4434
+ continue;
4435
+ }
4436
+
4437
+ if (start.parentNode !== marker.parentNode) {
4438
+ start = undefined;
4439
+ continue;
4440
+ }
4441
+
4442
+ const children = [];
4443
+ let current = start.nextSibling;
4444
+
4445
+ while (current !== null && current !== marker) {
4446
+ const next = current.nextSibling;
4447
+ current.remove();
4448
+ children.push(current);
4449
+ current = next;
4450
+ }
4451
+
4452
+ start.remove();
4453
+ marker.remove();
4454
+ return children.length === 0 ? "" : children.length === 1 ? children[0] : children;
4455
+ }
4456
+
4457
+ return undefined;
4458
+ }
4459
+
4302
4460
  function __mreactResumeRoute(marker, nextNode) {
4303
4461
  if (nextNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
4304
4462
  marker.replaceChildren(nextNode);
@@ -4314,12 +4472,23 @@ function __mreactResumeRoute(marker, nextNode) {
4314
4472
 
4315
4473
  __mreactResumeNode(current, nextNode);
4316
4474
 
4317
- if (current.parentNode !== marker) {
4475
+ const active = current.parentNode === marker
4476
+ ? current
4477
+ : nextNode.parentNode === marker
4478
+ ? nextNode
4479
+ : null;
4480
+
4481
+ if (active === null) {
4318
4482
  return;
4319
4483
  }
4320
4484
 
4321
- while (marker.childNodes.length > 1) {
4322
- marker.lastChild?.remove();
4485
+ for (const child of Array.from(marker.childNodes)) {
4486
+ if (child === active) {
4487
+ continue;
4488
+ }
4489
+
4490
+ __mreactUnmountCompatBoundaries(child);
4491
+ child.remove();
4323
4492
  }
4324
4493
  }
4325
4494
 
@@ -4395,6 +4564,7 @@ function __mreactResumeNode(current, next) {
4395
4564
  }
4396
4565
 
4397
4566
  __mreactSyncEventBindings(current, next);
4567
+ __mreactSyncDomRefBindings(current, next);
4398
4568
  __mreactSyncAttributes(current, next);
4399
4569
  __mreactSyncPropBindings(current, next);
4400
4570
  __mreactResumeChildren(current, next);
@@ -4417,6 +4587,7 @@ function __mreactShouldReplaceNode(current, next) {
4417
4587
  }
4418
4588
 
4419
4589
  ${routeEventBindingSyncFunction}
4590
+ ${routeDomRefBindingSyncFunction}
4420
4591
 
4421
4592
  function __mreactSyncAttributes(current, next) {
4422
4593
  for (const attribute of Array.from(current.attributes)) {
@@ -4436,9 +4607,7 @@ function __mreactSyncPropBindings(current, next) {
4436
4607
  const previousBindings = current.__mreactPropBindings;
4437
4608
 
4438
4609
  if (Array.isArray(previousBindings)) {
4439
- for (const binding of previousBindings) {
4440
- binding.dispose?.();
4441
- }
4610
+ __mreactRunLifecycleTasks(previousBindings, (binding) => binding.dispose?.());
4442
4611
  }
4443
4612
 
4444
4613
  const bindings = next.__mreactPropBindings;
@@ -4454,9 +4623,7 @@ function __mreactSyncPropBindings(current, next) {
4454
4623
  next.__mreactPropBindings = [];
4455
4624
  next.__mreactHasReactiveProps = false;
4456
4625
 
4457
- for (const binding of bindings) {
4458
- binding.retarget?.(current);
4459
- }
4626
+ __mreactRunLifecycleTasks(bindings, (binding) => binding.retarget?.(current));
4460
4627
  }
4461
4628
 
4462
4629
  function __mreactResumeChildren(current, next) {
@@ -4509,7 +4676,11 @@ function __mreactResumeChildren(current, next) {
4509
4676
  };
4510
4677
  }
4511
4678
 
4512
- function workspaceRuntimePlugin(options: { routeFiles: readonly string[] }) {
4679
+ function workspaceRuntimePlugin(options: {
4680
+ debugLabels: boolean;
4681
+ routeFiles: readonly string[];
4682
+ sourceRegionModulePaths?: Set<string> | undefined;
4683
+ }) {
4513
4684
  const routeFiles = new Set(options.routeFiles);
4514
4685
  const packageFile = (monorepoDir: string, packageName: string, entry: string): string =>
4515
4686
  workspacePackageFile({
@@ -4637,15 +4808,31 @@ export function invalidateReactiveDevtoolsCache() {}
4637
4808
  export function prepareReactiveEffectRunDevtoolsEvent() { return undefined; }`,
4638
4809
  loader: "ts",
4639
4810
  }));
4811
+ if (options.sourceRegionModulePaths !== undefined) {
4812
+ buildApi.onLoad({ filter: /.*/ }, (args) => {
4813
+ if (
4814
+ isAbsolute(args.path) &&
4815
+ isRouteClientDependencySourcePath(args.path, routeFiles) &&
4816
+ !runtimePackageDirs.some(
4817
+ (runtimePackageDir) => args.path.startsWith(`${runtimePackageDir}${sep}`),
4818
+ )
4819
+ ) {
4820
+ options.sourceRegionModulePaths?.add(args.path);
4821
+ }
4822
+
4823
+ return undefined;
4824
+ });
4825
+ }
4640
4826
  buildApi.onLoad({ filter: /\.(?:mreact\.)?[cm]?[jt]sx$/ }, async (args) => {
4641
4827
  if (!isRouteClientDependencySourcePath(args.path, routeFiles)) {
4642
4828
  return undefined;
4643
4829
  }
4644
4830
 
4645
4831
  const source = await readFile(args.path, "utf8");
4832
+ const compilerFilename = options.debugLabels ? basename(args.path) : args.path;
4646
4833
  const moduleContext = createCompilerModuleContext({
4647
4834
  code: source,
4648
- filename: args.path,
4835
+ filename: compilerFilename,
4649
4836
  });
4650
4837
 
4651
4838
  if (!hasJsxSyntax(moduleContext.program)) {
@@ -4654,8 +4841,8 @@ export function prepareReactiveEffectRunDevtoolsEvent() { return undefined; }`,
4654
4841
 
4655
4842
  const output = transformCompilerModuleContext({
4656
4843
  code: source,
4657
- dev: true,
4658
- filename: args.path,
4844
+ dev: options.debugLabels,
4845
+ filename: compilerFilename,
4659
4846
  mode: isCompatSourcePath(args.path) ? "compat" : "reactive",
4660
4847
  moduleContext,
4661
4848
  target: "client",
package/src/vite.ts CHANGED
@@ -848,6 +848,7 @@ async function renderAppRouterClientRouteDevModule(
848
848
  clientReferenceImports: references.clientReferenceImports,
849
849
  clientReferenceManifest: references.clientReferenceManifest,
850
850
  clientNavigation: navigation || detectAnchorElementUsage(clientSource, route.file),
851
+ debugLabels: true,
851
852
  filename: route.file,
852
853
  routeMayUseOutOfOrderFragments: true,
853
854
  routePath: route.path,