@reckona/mreact-router 0.0.186 → 0.0.187
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/build.d.ts.map +1 -1
- package/dist/build.js +4 -2
- package/dist/build.js.map +1 -1
- package/dist/bundle-pipeline.d.ts +1 -0
- package/dist/bundle-pipeline.d.ts.map +1 -1
- package/dist/bundle-pipeline.js +9 -3
- package/dist/bundle-pipeline.js.map +1 -1
- package/dist/client-route-inference.d.ts +1 -1
- package/dist/client-route-inference.d.ts.map +1 -1
- package/dist/client-route-inference.js +1 -1
- package/dist/client-route-inference.js.map +1 -1
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +108 -187
- package/dist/client.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +1 -0
- package/dist/render.js.map +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +23 -1
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/build.ts +9 -2
- package/src/bundle-pipeline.ts +12 -3
- package/src/client-route-inference.ts +2 -0
- package/src/client.ts +134 -187
- package/src/render.ts +1 -0
- package/src/vite.ts +23 -0
package/src/client.ts
CHANGED
|
@@ -80,6 +80,7 @@ export interface BuildClientRouteOutputOptions {
|
|
|
80
80
|
vitePlugins?: readonly PluginOption[] | undefined;
|
|
81
81
|
clientNavigation?: boolean | undefined;
|
|
82
82
|
forceInlineNavigationRuntime?: boolean | undefined;
|
|
83
|
+
routeMayUseOutOfOrderFragments?: boolean | undefined;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
export interface BuildClientRouteBatchOutput {
|
|
@@ -2067,7 +2068,9 @@ export async function buildClientRouteBundle(options: {
|
|
|
2067
2068
|
clientBoundaryImports?: readonly string[] | undefined;
|
|
2068
2069
|
clientReferenceImports?: readonly ClientReferenceImport[] | undefined;
|
|
2069
2070
|
clientReferenceManifest?: readonly ClientReferenceMetadata[] | undefined;
|
|
2071
|
+
clientNavigation?: boolean | undefined;
|
|
2070
2072
|
filename: string;
|
|
2073
|
+
routeMayUseOutOfOrderFragments?: boolean | undefined;
|
|
2071
2074
|
routePath: string;
|
|
2072
2075
|
vitePlugins?: readonly PluginOption[] | undefined;
|
|
2073
2076
|
}): Promise<string> {
|
|
@@ -2241,6 +2244,12 @@ export async function buildClientRouteEntrySource(
|
|
|
2241
2244
|
options.filename,
|
|
2242
2245
|
);
|
|
2243
2246
|
const routeHasEventBindings = (compiled.metadata.eventHydrationManifest?.events.length ?? 0) > 0;
|
|
2247
|
+
const routeCapturesEventBindings = compiled.code.includes("__mreactEventBindings");
|
|
2248
|
+
const routeMayCaptureEventBindings =
|
|
2249
|
+
routeHasEventBindings ||
|
|
2250
|
+
routeCapturesEventBindings ||
|
|
2251
|
+
/\bon[A-Z][\w$]*\s*=/.test(options.code) ||
|
|
2252
|
+
routeSourceAnalysis.staticImports.length > 0;
|
|
2244
2253
|
const routeRequiresFullHydration =
|
|
2245
2254
|
routeExplicitlyRequiresHydration ||
|
|
2246
2255
|
routeUsesCells ||
|
|
@@ -2261,8 +2270,13 @@ export async function buildClientRouteEntrySource(
|
|
|
2261
2270
|
const routeCleanupScopeImport = routeUsesCleanupScope
|
|
2262
2271
|
? `import { withCleanupScope as __mreactWithCleanupScope } from "@reckona/mreact-reactive-core/internal";\n`
|
|
2263
2272
|
: "";
|
|
2273
|
+
const routeUsesEventBindingSync =
|
|
2274
|
+
!routeUsesOnlyClientReferenceBoundaries && routeMayCaptureEventBindings;
|
|
2275
|
+
const routeCapturedEventImport = routeUsesEventBindingSync
|
|
2276
|
+
? `import { bindCapturedEvent as __mreactBindCapturedEvent } from "@reckona/mreact-reactive-dom/internal";\n`
|
|
2277
|
+
: "";
|
|
2264
2278
|
const routeReactiveDomMetadataImport = !routeUsesOnlyClientReferenceBoundaries
|
|
2265
|
-
?
|
|
2279
|
+
? `${routeCapturedEventImport}import { withEventBindingMetadata as __mreactWithEventBindingMetadata, withPropBindingMetadata as __mreactWithPropBindingMetadata } from "@reckona/mreact-reactive-dom";\n`
|
|
2266
2280
|
: "";
|
|
2267
2281
|
const navigationStateDeclaration = inlineClientNavigation
|
|
2268
2282
|
? `const __mreactNavigationState = __mreactGlobal.__mreactNavigationState ??= {
|
|
@@ -2420,10 +2434,16 @@ function __mreactInstallNavigation() {
|
|
|
2420
2434
|
}
|
|
2421
2435
|
};
|
|
2422
2436
|
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2437
|
+
const hasSameOriginAnchor = Array.from(document.querySelectorAll("a[href]")).some((anchor) =>
|
|
2438
|
+
anchor instanceof HTMLAnchorElement && anchor.origin === location.origin,
|
|
2439
|
+
);
|
|
2440
|
+
|
|
2441
|
+
if (hasSameOriginAnchor) {
|
|
2442
|
+
if (typeof requestIdleCallback === "function") {
|
|
2443
|
+
requestIdleCallback(load);
|
|
2444
|
+
} else {
|
|
2445
|
+
setTimeout(load, 0);
|
|
2446
|
+
}
|
|
2427
2447
|
}
|
|
2428
2448
|
|
|
2429
2449
|
addEventListener("popstate", load);
|
|
@@ -2617,6 +2637,51 @@ function __mreactResolveRouteNode(value) {
|
|
|
2617
2637
|
const routeHydrationNodeExpression = !routeUsesOnlyClientReferenceBoundaries
|
|
2618
2638
|
? `__mreactWithPropBindingMetadata(() => __mreactWithEventBindingMetadata(() => __mreactEvaluateHydrationNode(() => ${routeNodeExpression})))`
|
|
2619
2639
|
: `__mreactEvaluateHydrationNode(() => ${routeNodeExpression})`;
|
|
2640
|
+
const routeEventBindingSyncFunction = routeUsesEventBindingSync
|
|
2641
|
+
? `function __mreactSyncEventBindings(current, next) {
|
|
2642
|
+
const previousDisposers = current.__mreactEventDisposers;
|
|
2643
|
+
|
|
2644
|
+
if (Array.isArray(previousDisposers)) {
|
|
2645
|
+
for (const dispose of previousDisposers) {
|
|
2646
|
+
dispose();
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
const rawBindings = next.__mreactEventBindings;
|
|
2651
|
+
const bindings =
|
|
2652
|
+
rawBindings === undefined ? [] : Array.isArray(rawBindings) ? rawBindings : [rawBindings];
|
|
2653
|
+
|
|
2654
|
+
if (bindings.length === 0) {
|
|
2655
|
+
current.__mreactEventDisposers = [];
|
|
2656
|
+
current.__mreactHasEvents = false;
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
const disposers = [];
|
|
2661
|
+
|
|
2662
|
+
for (const binding of bindings) {
|
|
2663
|
+
disposers.push(
|
|
2664
|
+
__mreactBindCapturedEvent(current, binding.type, binding.listener, binding.delegated === true),
|
|
2665
|
+
);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
current.__mreactEventDisposers = disposers;
|
|
2669
|
+
current.__mreactHasEvents = true;
|
|
2670
|
+
}
|
|
2671
|
+
`
|
|
2672
|
+
: `function __mreactSyncEventBindings(current) {
|
|
2673
|
+
const previousDisposers = current.__mreactEventDisposers;
|
|
2674
|
+
|
|
2675
|
+
if (Array.isArray(previousDisposers)) {
|
|
2676
|
+
for (const dispose of previousDisposers) {
|
|
2677
|
+
dispose();
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
current.__mreactEventDisposers = [];
|
|
2682
|
+
current.__mreactHasEvents = false;
|
|
2683
|
+
}
|
|
2684
|
+
`;
|
|
2620
2685
|
const boundaryOnlyHydrationBlock = routeRequiresFullHydration
|
|
2621
2686
|
? ""
|
|
2622
2687
|
: `${routeCellHydrationIndent}if (!__mreactHasNonSerializableClientBoundaries(__mreactMarker) && __mreactHydrateClientBoundaries(document, __mreactClientReferences, __mreactClientReferenceComponents)) {
|
|
@@ -2625,6 +2690,10 @@ ${routeCellHydrationIndent} __mreactMarkRouteHydrated();
|
|
|
2625
2690
|
${routeCellHydrationIndent} return;
|
|
2626
2691
|
${routeCellHydrationIndent}}
|
|
2627
2692
|
`;
|
|
2693
|
+
const routeOutOfOrderFragmentHydration =
|
|
2694
|
+
options.routeMayUseOutOfOrderFragments === true
|
|
2695
|
+
? " __mreactApplyOutOfOrderFragments(document);\n"
|
|
2696
|
+
: "";
|
|
2628
2697
|
const routeComponentGuard = `${routeCellHydrationIndent}if (__mreactComponent === undefined) {
|
|
2629
2698
|
${routeCellHydrationIndent} return;
|
|
2630
2699
|
${routeCellHydrationIndent}}
|
|
@@ -2647,8 +2716,7 @@ ${clientReferenceRegistry}
|
|
|
2647
2716
|
${routeNodeResolver}
|
|
2648
2717
|
|
|
2649
2718
|
export function __mreactHydrateRoute() {
|
|
2650
|
-
|
|
2651
|
-
const __mreactMarker = document.querySelector(\`[\${__mreactRouteMarkerAttribute}="\${__mreactRouteId}"]\`);
|
|
2719
|
+
${routeOutOfOrderFragmentHydration} const __mreactMarker = document.querySelector(\`[\${__mreactRouteMarkerAttribute}="\${__mreactRouteId}"]\`);
|
|
2652
2720
|
const __mreactPropsElement = document.getElementById(\`\${__mreactPropsScriptPrefix}\${__mreactRouteId}\`);
|
|
2653
2721
|
const __mreactClientReferencesElement = document.getElementById(\`\${__mreactClientReferencesScriptPrefix}\${__mreactRouteId}\`);
|
|
2654
2722
|
const __mreactPropsText = __mreactPropsElement?.textContent;
|
|
@@ -4347,184 +4415,7 @@ function __mreactShouldReplaceNode(current, next) {
|
|
|
4347
4415
|
current.tagName !== next.tagName;
|
|
4348
4416
|
}
|
|
4349
4417
|
|
|
4350
|
-
|
|
4351
|
-
const previousDisposers = current.__mreactEventDisposers;
|
|
4352
|
-
|
|
4353
|
-
if (Array.isArray(previousDisposers)) {
|
|
4354
|
-
for (const dispose of previousDisposers) {
|
|
4355
|
-
dispose();
|
|
4356
|
-
}
|
|
4357
|
-
}
|
|
4358
|
-
|
|
4359
|
-
const rawBindings = next.__mreactEventBindings;
|
|
4360
|
-
const bindings =
|
|
4361
|
-
rawBindings === undefined ? [] : Array.isArray(rawBindings) ? rawBindings : [rawBindings];
|
|
4362
|
-
|
|
4363
|
-
if (bindings.length === 0) {
|
|
4364
|
-
current.__mreactEventDisposers = [];
|
|
4365
|
-
current.__mreactHasEvents = false;
|
|
4366
|
-
return;
|
|
4367
|
-
}
|
|
4368
|
-
|
|
4369
|
-
const disposers = [];
|
|
4370
|
-
|
|
4371
|
-
for (const binding of bindings) {
|
|
4372
|
-
if (binding.delegated === true && __mreactIsDelegatedEventType(binding.type)) {
|
|
4373
|
-
disposers.push(__mreactAddDelegatedEventListener(current, binding.type, binding.listener));
|
|
4374
|
-
} else {
|
|
4375
|
-
current.addEventListener(binding.type, binding.listener);
|
|
4376
|
-
disposers.push(() => current.removeEventListener(binding.type, binding.listener));
|
|
4377
|
-
}
|
|
4378
|
-
}
|
|
4379
|
-
|
|
4380
|
-
current.__mreactEventDisposers = disposers;
|
|
4381
|
-
current.__mreactHasEvents = true;
|
|
4382
|
-
}
|
|
4383
|
-
|
|
4384
|
-
function __mreactIsDelegatedEventType(type) {
|
|
4385
|
-
return type === "change" ||
|
|
4386
|
-
type === "click" ||
|
|
4387
|
-
type === "input" ||
|
|
4388
|
-
type === "keydown" ||
|
|
4389
|
-
type === "keyup" ||
|
|
4390
|
-
type === "pointerdown" ||
|
|
4391
|
-
type === "pointermove" ||
|
|
4392
|
-
type === "pointerup" ||
|
|
4393
|
-
type === "submit";
|
|
4394
|
-
}
|
|
4395
|
-
|
|
4396
|
-
function __mreactDelegatedEventState() {
|
|
4397
|
-
globalThis.__mreactDelegatedEventState ??= {
|
|
4398
|
-
elements: new WeakMap(),
|
|
4399
|
-
roots: new WeakMap(),
|
|
4400
|
-
};
|
|
4401
|
-
return globalThis.__mreactDelegatedEventState;
|
|
4402
|
-
}
|
|
4403
|
-
|
|
4404
|
-
function __mreactAddDelegatedEventListener(element, type, listener) {
|
|
4405
|
-
const root = element.ownerDocument;
|
|
4406
|
-
const state = __mreactDelegatedEventState();
|
|
4407
|
-
let listenersByType = state.elements.get(element);
|
|
4408
|
-
|
|
4409
|
-
if (listenersByType === undefined) {
|
|
4410
|
-
listenersByType = new Map();
|
|
4411
|
-
state.elements.set(element, listenersByType);
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
|
-
let listeners = listenersByType.get(type);
|
|
4415
|
-
|
|
4416
|
-
if (listeners === undefined) {
|
|
4417
|
-
listeners = [];
|
|
4418
|
-
listenersByType.set(type, listeners);
|
|
4419
|
-
}
|
|
4420
|
-
|
|
4421
|
-
listeners.push(listener);
|
|
4422
|
-
__mreactRetainDelegatedEventRoot(root, type);
|
|
4423
|
-
|
|
4424
|
-
return () => {
|
|
4425
|
-
const state = __mreactDelegatedEventState();
|
|
4426
|
-
const currentListeners = state.elements.get(element)?.get(type);
|
|
4427
|
-
const index = currentListeners?.indexOf(listener) ?? -1;
|
|
4428
|
-
|
|
4429
|
-
if (index !== -1) {
|
|
4430
|
-
currentListeners?.splice(index, 1);
|
|
4431
|
-
}
|
|
4432
|
-
|
|
4433
|
-
if (currentListeners?.length === 0) {
|
|
4434
|
-
state.elements.get(element)?.delete(type);
|
|
4435
|
-
}
|
|
4436
|
-
|
|
4437
|
-
__mreactReleaseDelegatedEventRoot(root, type);
|
|
4438
|
-
};
|
|
4439
|
-
}
|
|
4440
|
-
|
|
4441
|
-
function __mreactRetainDelegatedEventRoot(root, type) {
|
|
4442
|
-
const state = __mreactDelegatedEventState();
|
|
4443
|
-
let rootsByType = state.roots.get(root);
|
|
4444
|
-
|
|
4445
|
-
if (rootsByType === undefined) {
|
|
4446
|
-
rootsByType = new Map();
|
|
4447
|
-
state.roots.set(root, rootsByType);
|
|
4448
|
-
}
|
|
4449
|
-
|
|
4450
|
-
const current = rootsByType.get(type);
|
|
4451
|
-
|
|
4452
|
-
if (current !== undefined) {
|
|
4453
|
-
current.count += 1;
|
|
4454
|
-
return;
|
|
4455
|
-
}
|
|
4456
|
-
|
|
4457
|
-
const listener = (event) => __mreactDispatchDelegatedEvent(root, type, event);
|
|
4458
|
-
rootsByType.set(type, { count: 1, listener });
|
|
4459
|
-
root.addEventListener(type, listener);
|
|
4460
|
-
}
|
|
4461
|
-
|
|
4462
|
-
function __mreactReleaseDelegatedEventRoot(root, type) {
|
|
4463
|
-
const rootsByType = __mreactDelegatedEventState().roots.get(root);
|
|
4464
|
-
const current = rootsByType?.get(type);
|
|
4465
|
-
|
|
4466
|
-
if (rootsByType === undefined || current === undefined) {
|
|
4467
|
-
return;
|
|
4468
|
-
}
|
|
4469
|
-
|
|
4470
|
-
current.count -= 1;
|
|
4471
|
-
|
|
4472
|
-
if (current.count > 0) {
|
|
4473
|
-
return;
|
|
4474
|
-
}
|
|
4475
|
-
|
|
4476
|
-
root.removeEventListener(type, current.listener);
|
|
4477
|
-
rootsByType.delete(type);
|
|
4478
|
-
}
|
|
4479
|
-
|
|
4480
|
-
function __mreactDispatchDelegatedEvent(root, type, event) {
|
|
4481
|
-
const state = __mreactDelegatedEventState();
|
|
4482
|
-
|
|
4483
|
-
for (const target of event.composedPath()) {
|
|
4484
|
-
if (target === root) {
|
|
4485
|
-
break;
|
|
4486
|
-
}
|
|
4487
|
-
|
|
4488
|
-
if (!(target instanceof HTMLElement)) {
|
|
4489
|
-
continue;
|
|
4490
|
-
}
|
|
4491
|
-
|
|
4492
|
-
const listeners = state.elements.get(target)?.get(type);
|
|
4493
|
-
|
|
4494
|
-
if (listeners === undefined || listeners.length === 0) {
|
|
4495
|
-
continue;
|
|
4496
|
-
}
|
|
4497
|
-
|
|
4498
|
-
const activeListeners = listeners.slice();
|
|
4499
|
-
|
|
4500
|
-
for (const listener of activeListeners) {
|
|
4501
|
-
__mreactCallWithCurrentTarget(listener, event, target);
|
|
4502
|
-
}
|
|
4503
|
-
|
|
4504
|
-
if (event.cancelBubble) {
|
|
4505
|
-
break;
|
|
4506
|
-
}
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
|
|
4510
|
-
function __mreactCallWithCurrentTarget(listener, event, currentTarget) {
|
|
4511
|
-
const descriptor = Object.getOwnPropertyDescriptor(event, "currentTarget");
|
|
4512
|
-
|
|
4513
|
-
Object.defineProperty(event, "currentTarget", {
|
|
4514
|
-
configurable: true,
|
|
4515
|
-
value: currentTarget,
|
|
4516
|
-
});
|
|
4517
|
-
|
|
4518
|
-
try {
|
|
4519
|
-
listener.call(currentTarget, event);
|
|
4520
|
-
} finally {
|
|
4521
|
-
if (descriptor === undefined) {
|
|
4522
|
-
delete event.currentTarget;
|
|
4523
|
-
} else {
|
|
4524
|
-
Object.defineProperty(event, "currentTarget", descriptor);
|
|
4525
|
-
}
|
|
4526
|
-
}
|
|
4527
|
-
}
|
|
4418
|
+
${routeEventBindingSyncFunction}
|
|
4528
4419
|
|
|
4529
4420
|
function __mreactSyncAttributes(current, next) {
|
|
4530
4421
|
for (const attribute of Array.from(current.attributes)) {
|
|
@@ -4653,6 +4544,10 @@ function workspaceRuntimePlugin(options: { routeFiles: readonly string[] }) {
|
|
|
4653
4544
|
packageFile("reactive-core", "@reckona/mreact-reactive-core", "internal"),
|
|
4654
4545
|
],
|
|
4655
4546
|
["@reckona/mreact-compat", reactCompatPath],
|
|
4547
|
+
[
|
|
4548
|
+
"@reckona/mreact-reactive-dom/internal",
|
|
4549
|
+
packageFile("reactive-dom", "@reckona/mreact-reactive-dom", "internal"),
|
|
4550
|
+
],
|
|
4656
4551
|
[
|
|
4657
4552
|
"@reckona/mreact-compat/event-priority",
|
|
4658
4553
|
packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
|
|
@@ -4733,9 +4628,12 @@ export function cell(initial) {
|
|
|
4733
4628
|
}));
|
|
4734
4629
|
buildApi.onLoad({ filter: /^devtools$/, namespace: "mreact-devtools-stub" }, () => ({
|
|
4735
4630
|
contents: `export function emitReactiveDevtoolsEvent() {}
|
|
4631
|
+
export function emitReactiveEffectRunDevtoolsEvent() {}
|
|
4736
4632
|
export function hasReactiveDevtoolsEmitter() { return false; }
|
|
4737
4633
|
export function currentDevtoolsEmitter() { return undefined; }
|
|
4738
|
-
export function currentReactiveDevtools() { return undefined; }
|
|
4634
|
+
export function currentReactiveDevtools() { return undefined; }
|
|
4635
|
+
export function invalidateReactiveDevtoolsCache() {}
|
|
4636
|
+
export function prepareReactiveEffectRunDevtoolsEvent() { return undefined; }`,
|
|
4739
4637
|
loader: "ts",
|
|
4740
4638
|
}));
|
|
4741
4639
|
buildApi.onLoad({ filter: /\.(?:mreact\.)?[cm]?[jt]sx$/ }, async (args) => {
|
|
@@ -4813,7 +4711,56 @@ function importerInRuntimePackage(
|
|
|
4813
4711
|
* not mistaken for a real export.
|
|
4814
4712
|
*/
|
|
4815
4713
|
export function detectClientNavigationHint(source: string): boolean {
|
|
4816
|
-
return
|
|
4714
|
+
return detectClientNavigationOverride(source) ?? true;
|
|
4715
|
+
}
|
|
4716
|
+
|
|
4717
|
+
export function detectClientNavigationOverride(source: string): boolean | undefined {
|
|
4718
|
+
return readTopLevelBooleanExport({ code: source, name: "clientNavigation" });
|
|
4719
|
+
}
|
|
4720
|
+
|
|
4721
|
+
export function detectAnchorElementUsage(source: string, filename?: string | undefined): boolean {
|
|
4722
|
+
const context = createCompilerModuleContext({ code: source, filename });
|
|
4723
|
+
return containsAnchorElementWithHref(context.program);
|
|
4724
|
+
}
|
|
4725
|
+
|
|
4726
|
+
function containsAnchorElementWithHref(value: unknown): boolean {
|
|
4727
|
+
if (value === null || typeof value !== "object") {
|
|
4728
|
+
return false;
|
|
4729
|
+
}
|
|
4730
|
+
|
|
4731
|
+
if (Array.isArray(value)) {
|
|
4732
|
+
return value.some((entry) => containsAnchorElementWithHref(entry));
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
const node = value as {
|
|
4736
|
+
attributes?: unknown;
|
|
4737
|
+
name?: { name?: unknown } | undefined;
|
|
4738
|
+
openingElement?:
|
|
4739
|
+
| {
|
|
4740
|
+
attributes?: unknown;
|
|
4741
|
+
name?: { name?: unknown } | undefined;
|
|
4742
|
+
}
|
|
4743
|
+
| undefined;
|
|
4744
|
+
type?: unknown;
|
|
4745
|
+
};
|
|
4746
|
+
|
|
4747
|
+
if (node.type === "JSXElement" && node.openingElement !== undefined) {
|
|
4748
|
+
const opening = node.openingElement;
|
|
4749
|
+
const tagName = opening?.name?.name;
|
|
4750
|
+
|
|
4751
|
+
if (
|
|
4752
|
+
tagName === "a" &&
|
|
4753
|
+
Array.isArray(opening.attributes) &&
|
|
4754
|
+
opening.attributes.some((attribute) => {
|
|
4755
|
+
const jsxAttribute = attribute as { name?: { name?: unknown }; type?: unknown };
|
|
4756
|
+
return jsxAttribute.type === "JSXAttribute" && jsxAttribute.name?.name === "href";
|
|
4757
|
+
})
|
|
4758
|
+
) {
|
|
4759
|
+
return true;
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
|
|
4763
|
+
return Object.values(value).some((entry) => containsAnchorElementWithHref(entry));
|
|
4817
4764
|
}
|
|
4818
4765
|
|
|
4819
4766
|
// `Link` ships from the dedicated `/link` subpath and is also re-exported from
|
package/src/render.ts
CHANGED
|
@@ -2658,6 +2658,7 @@ export async function bundleMiddlewareModuleCode(options: {
|
|
|
2658
2658
|
code: options.code,
|
|
2659
2659
|
define: options.define,
|
|
2660
2660
|
filename: options.file,
|
|
2661
|
+
externalizeMreactRuntimeAliases: true,
|
|
2661
2662
|
platform: "node",
|
|
2662
2663
|
root: options.importPolicy?.projectRoot,
|
|
2663
2664
|
plugins: [
|
package/src/vite.ts
CHANGED
|
@@ -25,6 +25,7 @@ import type { AppRouterImportPolicy } from "./import-policy.js";
|
|
|
25
25
|
import {
|
|
26
26
|
collectClientRouteReferences,
|
|
27
27
|
createClientRouteInferenceCache,
|
|
28
|
+
detectAnchorElementUsage,
|
|
28
29
|
formatClientRouteInferenceDiagnostic,
|
|
29
30
|
isClientRouteSource,
|
|
30
31
|
navigationRuntimeLinkDisabledDiagnostic,
|
|
@@ -149,6 +150,10 @@ export function createAppRouterVitePlugin(options: AppRouterVitePluginOptions):
|
|
|
149
150
|
packageFile("reactive-core", "@reckona/mreact-reactive-core", "internal"),
|
|
150
151
|
],
|
|
151
152
|
["@reckona/mreact-reactive-dom", reactiveDomPath],
|
|
153
|
+
[
|
|
154
|
+
"@reckona/mreact-reactive-dom/internal",
|
|
155
|
+
packageFile("reactive-dom", "@reckona/mreact-reactive-dom", "internal"),
|
|
156
|
+
],
|
|
152
157
|
["@reckona/mreact-compat", reactCompatPath],
|
|
153
158
|
[
|
|
154
159
|
"@reckona/mreact-compat/event-priority",
|
|
@@ -699,12 +704,21 @@ export async function renderAppRouterClientAsset(
|
|
|
699
704
|
let bundle: string;
|
|
700
705
|
|
|
701
706
|
try {
|
|
707
|
+
const navigation = await resolveNavigationRuntime({
|
|
708
|
+
appDir,
|
|
709
|
+
code,
|
|
710
|
+
filename: route.file,
|
|
711
|
+
references,
|
|
712
|
+
vitePlugins: options.vitePlugins,
|
|
713
|
+
});
|
|
702
714
|
bundle = await buildClientRouteBundle({
|
|
703
715
|
code: clientSource,
|
|
704
716
|
clientBoundaryImports: references.clientBoundaryImports,
|
|
705
717
|
clientReferenceImports: references.clientReferenceImports,
|
|
706
718
|
clientReferenceManifest: references.clientReferenceManifest,
|
|
719
|
+
clientNavigation: navigation || detectAnchorElementUsage(clientSource, route.file),
|
|
707
720
|
filename: route.file,
|
|
721
|
+
routeMayUseOutOfOrderFragments: true,
|
|
708
722
|
routePath: route.path,
|
|
709
723
|
vitePlugins: options.vitePlugins,
|
|
710
724
|
});
|
|
@@ -749,12 +763,21 @@ async function renderAppRouterClientRouteDevModule(
|
|
|
749
763
|
);
|
|
750
764
|
}
|
|
751
765
|
|
|
766
|
+
const navigation = await resolveNavigationRuntime({
|
|
767
|
+
appDir,
|
|
768
|
+
code,
|
|
769
|
+
filename: route.file,
|
|
770
|
+
references,
|
|
771
|
+
vitePlugins: options.vitePlugins,
|
|
772
|
+
});
|
|
752
773
|
const entry = await buildClientRouteEntrySource({
|
|
753
774
|
code: clientSource,
|
|
754
775
|
clientBoundaryImports: references.clientBoundaryImports,
|
|
755
776
|
clientReferenceImports: references.clientReferenceImports,
|
|
756
777
|
clientReferenceManifest: references.clientReferenceManifest,
|
|
778
|
+
clientNavigation: navigation || detectAnchorElementUsage(clientSource, route.file),
|
|
757
779
|
filename: route.file,
|
|
780
|
+
routeMayUseOutOfOrderFragments: true,
|
|
758
781
|
routePath: route.path,
|
|
759
782
|
vitePlugins: options.vitePlugins,
|
|
760
783
|
});
|