Skip to content

Commit 19b9149

Browse files
committed
refactor: expose setMpaFallbackHref instead of global
1 parent effa015 commit 19b9149

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

packages/qwik-city/src/runtime/src/link-component.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { useLocation, useNavigate } from './use-functions';
1616
import { preloadRouteBundles } from './client-navigate';
1717
import { isDev } from '@builder.io/qwik';
1818
// @ts-expect-error we don't have types for the preloader yet
19-
import { p as preload } from '@builder.io/qwik/preloader';
19+
import { p as preload, f as setMpaFallbackHref } from '@builder.io/qwik/preloader';
2020

2121
/** @public */
2222
export const Link = component$<LinkProps>((props) => {
@@ -68,7 +68,7 @@ export const Link = component$<LinkProps>((props) => {
6868
const preventDefault = clientNavPath
6969
? sync$((event: MouseEvent, target: HTMLAnchorElement) => {
7070
if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
71-
(window as any).__qwikPendingFallbackHref = target.href;
71+
setMpaFallbackHref(target.href);
7272
event.preventDefault();
7373
}
7474
})
@@ -81,13 +81,12 @@ export const Link = component$<LinkProps>((props) => {
8181
if (elm.hasAttribute('q:nbs')) {
8282
// Allow bootstrapping into useNavigate.
8383
await nav(location.href, { type: 'popstate' });
84-
delete (window as any).__qwikPendingFallbackHref;
8584
} else if (elm.href) {
8685
elm.setAttribute('aria-pressed', 'true');
8786
await nav(elm.href, { forceReload: reload, replaceState, scroll });
8887
elm.removeAttribute('aria-pressed');
89-
delete (window as any).__qwikPendingFallbackHref;
9088
}
89+
setMpaFallbackHref(null);
9190
}
9291
})
9392
: undefined;

packages/qwik/src/core/preloader/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88

99
// Short names for minification
1010
export { loadBundleGraph as l, parseBundleGraph as g } from './bundle-graph';
11-
export { preload as p, handleBundle as h } from './queue';
11+
export { preload as p, handleBundle as h, setMpaFallbackHref as f } from './queue';

packages/qwik/src/core/preloader/queue.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const bundles: BundleImports = new Map();
1414
export let shouldResetFactor: boolean;
1515
let queueDirty: boolean;
1616
let preloadCount = 0;
17+
let pendingHref: string | undefined;
1718
const queue: BundleImport[] = [];
1819
const MPA_FALLBACK_THRESHOLD = 100;
1920

@@ -217,8 +218,6 @@ export const adjustProbabilities = (
217218
* something else, in which case we don't want to block reprioritization of this new event
218219
* bundles for too long. (If browsers supported aborting modulepreloads, we wouldn't have to
219220
* do this.)
220-
*
221-
* TODO: Set the limit to a number of kb instead of a number of bundles.
222221
*/
223222
if (probability === 1 || (probability >= 0.99 && depsCount <= MPA_FALLBACK_THRESHOLD + 1)) {
224223
depsCount++;
@@ -234,7 +233,7 @@ export const adjustProbabilities = (
234233
dep.$factor$ = factor;
235234
}
236235

237-
dispatchMPAFallback();
236+
fallbackToMpa();
238237

239238
adjustProbabilities(depBundle, newInverseProbability, seen);
240239
}
@@ -296,15 +295,40 @@ if (isBrowser) {
296295
* ~10s (usually between 3-7s).
297296
*
298297
* Note: if the next route bundles have already been preloaded, the fallback won't be triggered.
299-
*
300-
* TODO: get total kb size and compare with 100kb instead of relying on the number of bundles.
301298
*/
302-
const dispatchMPAFallback = () => {
299+
const fallbackToMpa = () => {
300+
if (!pendingHref) {
301+
return;
302+
}
303303
const nextRouteBundles = queue.filter((item) => item.$inverseProbability$ <= 0.1);
304304
if (nextRouteBundles.length >= MPA_FALLBACK_THRESHOLD) {
305-
const href = (window as any).__qwikPendingFallbackHref;
306-
if (href) {
307-
window.location.href = href;
305+
if (pendingHref !== window.location.href) {
306+
window.location.href = pendingHref;
307+
}
308+
}
309+
};
310+
311+
/**
312+
* Sets the MPA fallback href. When too many bundles are queued for preloading, the preloader will
313+
* redirect to this href using the browser navigation.
314+
*
315+
* @param href - The target URL for MPA fallback. Should be an absolute URL string or null/undefined
316+
* to clear it.
317+
* @returns Void
318+
*/
319+
export const setMpaFallbackHref = (href: string | null | undefined) => {
320+
if (!href || typeof href !== 'string') {
321+
pendingHref = undefined;
322+
return;
323+
}
324+
325+
try {
326+
const url = new URL(href, window.location.origin);
327+
pendingHref = url.href;
328+
} catch (error) {
329+
pendingHref = undefined;
330+
if (config.$DEBUG$) {
331+
console.warn('[Qwik Preloader] Invalid href provided to setSpaPendingHref:', href);
308332
}
309333
}
310334
};

0 commit comments

Comments
 (0)