diff --git a/packages/docs/src/routes/api/qwik-city/api.json b/packages/docs/src/routes/api/qwik-city/api.json index fe22bfc12ca..c3af9af9d6e 100644 --- a/packages/docs/src/routes/api/qwik-city/api.json +++ b/packages/docs/src/routes/api/qwik-city/api.json @@ -404,7 +404,7 @@ } ], "kind": "Interface", - "content": "```typescript\nexport interface LinkProps extends AnchorAttributes \n```\n**Extends:** AnchorAttributes\n\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[prefetch?](#)\n\n\n\n\n\n\n\nboolean \\| 'js'\n\n\n\n\n_(Optional)_ \\*\\*Defaults to \\_true\\_.\\*\\*\n\nWhether Qwik should prefetch and cache the target page of this \\*\\*`Link`\\*\\*, this includes invoking any \\*\\*`routeLoader$`\\*\\*, \\*\\*`onGet`\\*\\*, etc.\n\nThis \\*\\*improves UX performance\\*\\* for client-side (\\*\\*SPA\\*\\*) navigations.\n\nPrefetching occurs when a the Link enters the viewport in production (\\*\\*`on:qvisible`\\*\\*), or with \\*\\*`mouseover`/`focus`\\*\\* during dev.\n\nPrefetching will not occur if the user has the \\*\\*data saver\\*\\* setting enabled.\n\nSetting this value to \\*\\*`\"js\"`\\*\\* will prefetch only javascript bundles required to render this page on the client, \\*\\*`false`\\*\\* will disable prefetching altogether.\n\n\n
\n\n[reload?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
\n\n[replaceState?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
\n\n[scroll?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
", + "content": "```typescript\nexport interface LinkProps extends AnchorAttributes \n```\n**Extends:** AnchorAttributes\n\n\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[fallbackToMpa?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_ \\*\\*Defaults to \\_true\\_.\\*\\*\n\nWhether Qwik should fallback to MPA navigation if too many bundles are queued for preloading.\n\n\n
\n\n[prefetch?](#)\n\n\n\n\n\n\n\nboolean \\| 'js'\n\n\n\n\n_(Optional)_ \\*\\*Defaults to \\_true\\_.\\*\\*\n\nWhether Qwik should prefetch and cache the target page of this \\*\\*`Link`\\*\\*, this includes invoking any \\*\\*`routeLoader$`\\*\\*, \\*\\*`onGet`\\*\\*, etc.\n\nThis \\*\\*improves UX performance\\*\\* for client-side (\\*\\*SPA\\*\\*) navigations.\n\nPrefetching occurs when a the Link enters the viewport in production (\\*\\*`on:qvisible`\\*\\*), or with \\*\\*`mouseover`/`focus`\\*\\* during dev.\n\nPrefetching will not occur if the user has the \\*\\*data saver\\*\\* setting enabled.\n\nSetting this value to \\*\\*`\"js\"`\\*\\* will prefetch only javascript bundles required to render this page on the client, \\*\\*`false`\\*\\* will disable prefetching altogether.\n\n\n
\n\n[reload?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
\n\n[replaceState?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
\n\n[scroll?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_\n\n\n
", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-city/src/runtime/src/link-component.tsx", "mdFile": "qwik-city.linkprops.md" }, @@ -530,7 +530,7 @@ } ], "kind": "Interface", - "content": "```typescript\nexport interface QwikCityMockProps \n```\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[goto?](#)\n\n\n\n\n\n\n\n[RouteNavigate](#routenavigate)\n\n\n\n\n_(Optional)_\n\n\n
\n\n[params?](#)\n\n\n\n\n\n\n\nRecord<string, string>\n\n\n\n\n_(Optional)_\n\n\n
\n\n[url?](#)\n\n\n\n\n\n\n\nstring\n\n\n\n\n_(Optional)_\n\n\n
", + "content": "```typescript\nexport interface QwikCityMockProps \n```\n\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[fallbackToMpa?](#)\n\n\n\n\n\n\n\n{ default: boolean; }\n\n\n\n\n_(Optional)_\n\n\n
\n\n[goto?](#)\n\n\n\n\n\n\n\n[RouteNavigate](#routenavigate)\n\n\n\n\n_(Optional)_\n\n\n
\n\n[params?](#)\n\n\n\n\n\n\n\nRecord<string, string>\n\n\n\n\n_(Optional)_\n\n\n
\n\n[url?](#)\n\n\n\n\n\n\n\nstring\n\n\n\n\n_(Optional)_\n\n\n
", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-city/src/runtime/src/qwik-city-component.tsx", "mdFile": "qwik-city.qwikcitymockprops.md" }, @@ -572,7 +572,7 @@ } ], "kind": "Interface", - "content": "```typescript\nexport interface QwikCityProps \n```\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[viewTransition?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_ Enable the ViewTransition API\n\nDefault: `true`\n\n\n
", + "content": "```typescript\nexport interface QwikCityProps \n```\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[fallbackToMpa?](#)\n\n\n\n\n\n\n\n{ default: boolean; }\n\n\n\n\n_(Optional)_ Whether Qwik should fallback to MPA navigation if too many bundles are queued for preloading during SPA navigation.\n\n\n
\n\n[viewTransition?](#)\n\n\n\n\n\n\n\nboolean\n\n\n\n\n_(Optional)_ Enable the ViewTransition API\n\nDefault: `true`\n\n\n
", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik-city/src/runtime/src/qwik-city-component.tsx", "mdFile": "qwik-city.qwikcityprops.md" }, diff --git a/packages/docs/src/routes/api/qwik-city/index.mdx b/packages/docs/src/routes/api/qwik-city/index.mdx index db175d19d9f..32edb59acf5 100644 --- a/packages/docs/src/routes/api/qwik-city/index.mdx +++ b/packages/docs/src/routes/api/qwik-city/index.mdx @@ -1506,6 +1506,23 @@ Description +[fallbackToMpa?](#) + + + + + +boolean + + + +_(Optional)_ \*\*Defaults to \_true\_.\*\* + +Whether Qwik should fallback to MPA navigation if too many bundles are queued for preloading. + + + + [prefetch?](#) @@ -1764,6 +1781,21 @@ Description +[fallbackToMpa?](#) + + + + + +\{ default: boolean; } + + + +_(Optional)_ + + + + [goto?](#) @@ -1971,6 +2003,21 @@ Description +[fallbackToMpa?](#) + + + + + +\{ default: boolean; } + + + +_(Optional)_ Whether Qwik should fallback to MPA navigation if too many bundles are queued for preloading during SPA navigation. + + + + [viewTransition?](#) diff --git a/packages/docs/src/routes/api/qwik-optimizer/api.json b/packages/docs/src/routes/api/qwik-optimizer/api.json index 6d42fe4b24b..5141473853c 100644 --- a/packages/docs/src/routes/api/qwik-optimizer/api.json +++ b/packages/docs/src/routes/api/qwik-optimizer/api.json @@ -106,6 +106,23 @@ "content": "```typescript\ndirname(path: string): string;\n```\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\npath\n\n\n\n\nstring\n\n\n\n\n\n
\n\n**Returns:**\n\nstring", "mdFile": "qwik.path.dirname.md" }, + { + "name": "enableFallbackToMpa", + "id": "experimentalfeatures-enablefallbacktompa", + "hierarchy": [ + { + "name": "ExperimentalFeatures", + "id": "experimentalfeatures-enablefallbacktompa" + }, + { + "name": "enableFallbackToMpa", + "id": "experimentalfeatures-enablefallbacktompa" + } + ], + "kind": "EnumMember", + "content": "", + "mdFile": "qwik.experimentalfeatures.enablefallbacktompa.md" + }, { "name": "enableRequestRewrite", "id": "experimentalfeatures-enablerequestrewrite", @@ -147,7 +164,7 @@ } ], "kind": "Enum", - "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nUse `__EXPERIMENTAL__.x` to check if feature `x` is enabled. It will be replaced with `true` or `false` via an exact string replacement.\n\nAdd experimental features to this enum definition.\n\n\n```typescript\nexport declare enum ExperimentalFeatures \n```\n\n\n\n\n\n\n\n
\n\nMember\n\n\n\n\nValue\n\n\n\n\nDescription\n\n\n
\n\nenableRequestRewrite\n\n\n\n\n`\"enableRequestRewrite\"`\n\n\n\n\n**_(ALPHA)_** Enable request.rewrite()\n\n\n
\n\nnoSPA\n\n\n\n\n`\"noSPA\"`\n\n\n\n\n**_(ALPHA)_** Disable SPA navigation handler in Qwik City\n\n\n
\n\npreventNavigate\n\n\n\n\n`\"preventNavigate\"`\n\n\n\n\n**_(ALPHA)_** Enable the usePreventNavigate hook\n\n\n
\n\nvalibot\n\n\n\n\n`\"valibot\"`\n\n\n\n\n**_(ALPHA)_** Enable the Valibot form validation\n\n\n
", + "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nUse `__EXPERIMENTAL__.x` to check if feature `x` is enabled. It will be replaced with `true` or `false` via an exact string replacement.\n\nAdd experimental features to this enum definition.\n\n\n```typescript\nexport declare enum ExperimentalFeatures \n```\n\n\n\n\n\n\n\n\n
\n\nMember\n\n\n\n\nValue\n\n\n\n\nDescription\n\n\n
\n\nenableFallbackToMpa\n\n\n\n\n`\"enableFallbackToMpa\"`\n\n\n\n\n**_(ALPHA)_** Enable falling back to MPA when SPA navigation is slow, which can happen with a big page during preloading\n\n\n
\n\nenableRequestRewrite\n\n\n\n\n`\"enableRequestRewrite\"`\n\n\n\n\n**_(ALPHA)_** Enable request.rewrite()\n\n\n
\n\nnoSPA\n\n\n\n\n`\"noSPA\"`\n\n\n\n\n**_(ALPHA)_** Disable SPA navigation handler in Qwik City\n\n\n
\n\npreventNavigate\n\n\n\n\n`\"preventNavigate\"`\n\n\n\n\n**_(ALPHA)_** Enable the usePreventNavigate hook\n\n\n
\n\nvalibot\n\n\n\n\n`\"valibot\"`\n\n\n\n\n**_(ALPHA)_** Enable the Valibot form validation\n\n\n
", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/optimizer/src/plugins/plugin.ts", "mdFile": "qwik.experimentalfeatures.md" }, diff --git a/packages/docs/src/routes/api/qwik-optimizer/index.mdx b/packages/docs/src/routes/api/qwik-optimizer/index.mdx index 159d9d3c8e8..de24edf93ff 100644 --- a/packages/docs/src/routes/api/qwik-optimizer/index.mdx +++ b/packages/docs/src/routes/api/qwik-optimizer/index.mdx @@ -328,6 +328,8 @@ string string +## enableFallbackToMpa + ## enableRequestRewrite ## EntryStrategy @@ -374,6 +376,19 @@ Description +enableFallbackToMpa + + + +`"enableFallbackToMpa"` + + + +**_(ALPHA)_** Enable falling back to MPA when SPA navigation is slow, which can happen with a big page during preloading + + + + enableRequestRewrite diff --git a/packages/qwik-city/src/runtime/src/contexts.ts b/packages/qwik-city/src/runtime/src/contexts.ts index f0fc2f36080..05707c12741 100644 --- a/packages/qwik-city/src/runtime/src/contexts.ts +++ b/packages/qwik-city/src/runtime/src/contexts.ts @@ -29,3 +29,5 @@ export const RouteInternalContext = export const RoutePreventNavigateContext = /*#__PURE__*/ createContextId('qc-p'); + +export const fallbackToMpaContext = /*#__PURE__*/ createContextId<{ default: boolean }>('qc-f'); diff --git a/packages/qwik-city/src/runtime/src/link-component.tsx b/packages/qwik-city/src/runtime/src/link-component.tsx index 9ae80e3e20d..d9a5583ccd6 100644 --- a/packages/qwik-city/src/runtime/src/link-component.tsx +++ b/packages/qwik-city/src/runtime/src/link-component.tsx @@ -17,6 +17,7 @@ import { preloadRouteBundles } from './client-navigate'; import { isDev } from '@builder.io/qwik'; // @ts-expect-error we don't have types for the preloader yet import { p as preload } from '@builder.io/qwik/preloader'; +// import { fallbackToMpaContext } from './contexts'; /** @public */ export const Link = component$((props) => { @@ -24,14 +25,23 @@ export const Link = component$((props) => { const loc = useLocation(); const originalHref = props.href; const anchorRef = useSignal(); + const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, + fallbackToMpa: fallbackToMpaProp, ...linkProps } = (() => props)(); + + // const defaultFallbackToMpa = useContext(fallbackToMpaContext).default; + + // const fallbackToMpa = __EXPERIMENTAL__.enableFallbackToMpa + // ? untrack(() => Boolean(fallbackToMpaProp ?? defaultFallbackToMpa)) + // : undefined; + const clientNavPath = untrack(() => getClientNavPath({ ...linkProps, reload }, loc)); linkProps.href = clientNavPath || originalHref; @@ -66,7 +76,7 @@ export const Link = component$((props) => { : undefined; const preventDefault = clientNavPath - ? sync$((event: MouseEvent, target: HTMLAnchorElement) => { + ? sync$((event: MouseEvent) => { if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) { event.preventDefault(); } @@ -89,9 +99,27 @@ export const Link = component$((props) => { }) : undefined; - const handlePreload = $((_: any, elm: HTMLAnchorElement) => { - const url = new URL(elm.href); + const handlePreload = $((_: any, target: HTMLAnchorElement) => { + if (!target?.href) { + return; + } + const onTooMany = (event: Event) => { + const userEventPreloads = (event as CustomEvent).detail; + /** + * On chrome 3G throttling, 10kb takes ~1s to download. Bundles weight ~1kb on average, so 100 + * bundles is ~100kb which takes ~10s to download. + * + * This can serve to fallback to MPA when SPA navigation takes more than 10s. Or in extreme + * cases, if a component needs more than a 100 bundles, display a spinner. + */ + if (userEventPreloads.count >= 100) { + location.assign(target.href); + } + }; + window.addEventListener('userEventPreloads', onTooMany); + const url = new URL(target.href); preloadRouteBundles(url.pathname, 1); + window.removeEventListener('userEventPreloads', onTooMany); }); useVisibleTask$(({ track }) => { @@ -166,4 +194,11 @@ export interface LinkProps extends AnchorAttributes { reload?: boolean; replaceState?: boolean; scroll?: boolean; + + /** + * **Defaults to _true_.** + * + * Whether Qwik should fallback to MPA navigation if too many bundles are queued for preloading. + */ + fallbackToMpa?: boolean; } diff --git a/packages/qwik-city/src/runtime/src/qwik-city-component.tsx b/packages/qwik-city/src/runtime/src/qwik-city-component.tsx index 038f73c6667..4d4c82533f2 100644 --- a/packages/qwik-city/src/runtime/src/qwik-city-component.tsx +++ b/packages/qwik-city/src/runtime/src/qwik-city-component.tsx @@ -24,6 +24,7 @@ import { DocumentHeadContext, RouteActionContext, RouteInternalContext, + fallbackToMpaContext, RouteLocationContext, RouteNavigateContext, RoutePreventNavigateContext, @@ -89,6 +90,12 @@ export interface QwikCityProps { * @see https://caniuse.com/mdn-api_viewtransition */ viewTransition?: boolean; + + /** + * Whether Qwik should fallback to MPA navigation if too many bundles are queued for preloading + * during SPA navigation. + */ + fallbackToMpa?: { default: boolean }; } // Gets populated by registerPreventNav on the client @@ -307,6 +314,7 @@ export const QwikCityProvider = component$((props) => { useContextProvider(RouteActionContext, actionState); useContextProvider(RouteInternalContext, routeInternal); useContextProvider(RoutePreventNavigateContext, registerPreventNav); + useContextProvider(fallbackToMpaContext, props.fallbackToMpa ?? { default: false }); useTask$(({ track }) => { async function run() { @@ -646,6 +654,7 @@ export interface QwikCityMockProps { url?: string; params?: Record; goto?: RouteNavigate; + fallbackToMpa?: { default: boolean }; } /** @public */ @@ -693,6 +702,8 @@ export const QwikCityMockProvider = component$((props) => { useContextProvider(RouteStateContext, loaderState); useContextProvider(RouteActionContext, actionState); useContextProvider(RouteInternalContext, routeInternal); + console.log('props.fallbackToMpa', props.fallbackToMpa?.default); + useContextProvider(fallbackToMpaContext, props.fallbackToMpa ?? { default: false }); return ; }); diff --git a/packages/qwik-city/src/runtime/src/qwik-city.runtime.api.md b/packages/qwik-city/src/runtime/src/qwik-city.runtime.api.md index e4773ede255..5422e48a205 100644 --- a/packages/qwik-city/src/runtime/src/qwik-city.runtime.api.md +++ b/packages/qwik-city/src/runtime/src/qwik-city.runtime.api.md @@ -277,6 +277,7 @@ export const Link: Component; // // @public (undocumented) export interface LinkProps extends AnchorAttributes { + fallbackToMpa?: boolean; prefetch?: boolean | 'js'; // (undocumented) reload?: boolean; @@ -330,6 +331,10 @@ export const QWIK_CITY_SCROLLER = "_qCityScroller"; // @public (undocumented) export interface QwikCityMockProps { + // (undocumented) + fallbackToMpa?: { + default: boolean; + }; // (undocumented) goto?: RouteNavigate; // (undocumented) @@ -359,6 +364,9 @@ export interface QwikCityPlan { // @public (undocumented) export interface QwikCityProps { + fallbackToMpa?: { + default: boolean; + }; viewTransition?: boolean; } diff --git a/packages/qwik/src/core/preloader/preloader.unit.ts b/packages/qwik/src/core/preloader/preloader.unit.ts index 3cf4fa49f5a..b7568c3abc9 100644 --- a/packages/qwik/src/core/preloader/preloader.unit.ts +++ b/packages/qwik/src/core/preloader/preloader.unit.ts @@ -21,5 +21,5 @@ test('preloader script', () => { * dereference objects etc, but that actually results in worse compression */ const compressed = compress(Buffer.from(preLoader), { mode: 1, quality: 11 }); - expect([compressed.length, preLoader.length]).toEqual([1818, 5417]); + expect([compressed.length, preLoader.length]).toEqual([2031, 6129]); }); diff --git a/packages/qwik/src/core/preloader/queue.ts b/packages/qwik/src/core/preloader/queue.ts index f31e4eb83ba..fafbe0e8455 100644 --- a/packages/qwik/src/core/preloader/queue.ts +++ b/packages/qwik/src/core/preloader/queue.ts @@ -74,6 +74,11 @@ export const trigger = () => { } sortQueue(); while (queue.length) { + const userEventPreloads = queue.filter((item) => item.$inverseProbability$ <= 0.1); + dispatchEvent( + new CustomEvent('userEventPreloads', { detail: { count: userEventPreloads.length } }) + ); + const bundle = queue[0]; const inverseProbability = bundle.$inverseProbability$; const probability = 1 - inverseProbability; @@ -203,7 +208,21 @@ export const adjustProbabilities = ( * too. */ let newInverseProbability: number; - if (probability === 1 || (probability >= 0.99 && depsCount < 100)) { + + /** + * 100 deps to be preloaded at once would mean a ~10s delay on chrome 3G throttling. + * + * This can happen for Link components as they load all of the route bundles at once, but in + * this case we fallback to MPA. + * + * This should never happen for a normal component. But in case it happens, we set the limit + * based on OVERLY_SLOW_REPRIORITIZED_PRELOADING_DEFAULT_THRESHOLD + 1 === 101 (to ensure the + * fallback works), because if the user has to wait for 10s before anything happens it is + * possible that they try to click on something else, in which case we don't want to block + * reprioritization of this new event bundles for too long. (If browsers supported aborting + * modulepreloads, we wouldn't have to do this.) + */ + if (probability === 1 || (probability >= 0.99 && depsCount <= 101)) { depsCount++; // we're loaded at max probability, so elevate dynamic imports to 99% sure newInverseProbability = Math.min(0.01, 1 - dep.$importProbability$); @@ -225,6 +244,7 @@ export const adjustProbabilities = ( export const handleBundle = (name: string, inverseProbability: number) => { const bundle = getBundle(name); if (bundle && bundle.$inverseProbability$ > inverseProbability) { + // prioritize the event bundles first adjustProbabilities(bundle, inverseProbability); } }; diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.ts b/packages/qwik/src/optimizer/src/plugins/plugin.ts index 35ac8c78b3a..6e300334a57 100644 --- a/packages/qwik/src/optimizer/src/plugins/plugin.ts +++ b/packages/qwik/src/optimizer/src/plugins/plugin.ts @@ -66,6 +66,11 @@ const CLIENT_STRIP_CTX_NAME = [ * @alpha */ export enum ExperimentalFeatures { + /** + * Enable falling back to MPA when SPA navigation is slow, which can happen with a big page during + * preloading + */ + enableFallbackToMpa = 'enableFallbackToMpa', /** Enable the usePreventNavigate hook */ preventNavigate = 'preventNavigate', /** Enable the Valibot form validation */ diff --git a/packages/qwik/src/optimizer/src/qwik.optimizer.api.md b/packages/qwik/src/optimizer/src/qwik.optimizer.api.md index 6030200d353..75119e826bb 100644 --- a/packages/qwik/src/optimizer/src/qwik.optimizer.api.md +++ b/packages/qwik/src/optimizer/src/qwik.optimizer.api.md @@ -52,6 +52,7 @@ export type EntryStrategy = InlineEntryStrategy | HoistEntryStrategy | SingleEnt // @alpha export enum ExperimentalFeatures { + enableFallbackToMpa = "enableFallbackToMpa", enableRequestRewrite = "enableRequestRewrite", noSPA = "noSPA", preventNavigate = "preventNavigate", diff --git a/starters/apps/preloader-test/src/root.tsx b/starters/apps/preloader-test/src/root.tsx index 1fdb6ca6e59..573c8a9ff29 100644 --- a/starters/apps/preloader-test/src/root.tsx +++ b/starters/apps/preloader-test/src/root.tsx @@ -13,7 +13,7 @@ export default component$(() => { */ return ( - + diff --git a/starters/apps/preloader-test/src/routes/fallback/index.tsx b/starters/apps/preloader-test/src/routes/fallback/index.tsx new file mode 100644 index 00000000000..4d0874bea26 --- /dev/null +++ b/starters/apps/preloader-test/src/routes/fallback/index.tsx @@ -0,0 +1,224 @@ +import { component$ } from "@builder.io/qwik"; +import { Link } from "@builder.io/qwik-city"; +import Counter1 from "~/components/generated/counter1"; +import Counter2 from "~/components/generated/counter2"; +import Counter3 from "~/components/generated/counter3"; +import Counter4 from "~/components/generated/counter4"; +import Counter5 from "~/components/generated/counter5"; +import Counter6 from "~/components/generated/counter6"; +import Counter7 from "~/components/generated/counter7"; +import Counter8 from "~/components/generated/counter8"; +import Counter9 from "~/components/generated/counter9"; +import Counter10 from "~/components/generated/counter10"; +import Counter11 from "~/components/generated/counter11"; +import Counter12 from "~/components/generated/counter12"; +import Counter13 from "~/components/generated/counter13"; +import Counter14 from "~/components/generated/counter14"; +import Counter15 from "~/components/generated/counter15"; +import Counter16 from "~/components/generated/counter16"; +import Counter17 from "~/components/generated/counter17"; +import Counter18 from "~/components/generated/counter18"; +import Counter19 from "~/components/generated/counter19"; +import Counter20 from "~/components/generated/counter20"; +import Counter21 from "~/components/generated/counter21"; +import Counter22 from "~/components/generated/counter22"; +import Counter23 from "~/components/generated/counter23"; +import Counter24 from "~/components/generated/counter24"; +import Counter25 from "~/components/generated/counter25"; +import Counter26 from "~/components/generated/counter26"; +import Counter27 from "~/components/generated/counter27"; +import Counter28 from "~/components/generated/counter28"; +import Counter29 from "~/components/generated/counter29"; +import Counter30 from "~/components/generated/counter30"; +import Counter31 from "~/components/generated/counter31"; +import Counter32 from "~/components/generated/counter32"; +import Counter33 from "~/components/generated/counter33"; +import Counter34 from "~/components/generated/counter34"; +import Counter35 from "~/components/generated/counter35"; +import Counter36 from "~/components/generated/counter36"; +import Counter37 from "~/components/generated/counter37"; +import Counter38 from "~/components/generated/counter38"; +import Counter39 from "~/components/generated/counter39"; +import Counter40 from "~/components/generated/counter40"; +import Counter41 from "~/components/generated/counter41"; +import Counter42 from "~/components/generated/counter42"; +import Counter43 from "~/components/generated/counter43"; +import Counter44 from "~/components/generated/counter44"; +import Counter45 from "~/components/generated/counter45"; +import Counter46 from "~/components/generated/counter46"; +import Counter47 from "~/components/generated/counter47"; +import Counter48 from "~/components/generated/counter48"; +import Counter49 from "~/components/generated/counter49"; +import Counter50 from "~/components/generated/counter50"; +import Counter51 from "~/components/generated/counter51"; +import Counter52 from "~/components/generated/counter52"; +import Counter53 from "~/components/generated/counter53"; +import Counter54 from "~/components/generated/counter54"; +import Counter55 from "~/components/generated/counter55"; +import Counter56 from "~/components/generated/counter56"; +import Counter57 from "~/components/generated/counter57"; +import Counter58 from "~/components/generated/counter58"; +import Counter59 from "~/components/generated/counter59"; +import Counter60 from "~/components/generated/counter60"; +import Counter61 from "~/components/generated/counter61"; +import Counter62 from "~/components/generated/counter62"; +import Counter63 from "~/components/generated/counter63"; +import Counter64 from "~/components/generated/counter64"; +import Counter65 from "~/components/generated/counter65"; +import Counter66 from "~/components/generated/counter66"; +import Counter67 from "~/components/generated/counter67"; +import Counter68 from "~/components/generated/counter68"; +import Counter69 from "~/components/generated/counter69"; +import Counter70 from "~/components/generated/counter70"; +import Counter71 from "~/components/generated/counter71"; +import Counter72 from "~/components/generated/counter72"; +import Counter73 from "~/components/generated/counter73"; +import Counter74 from "~/components/generated/counter74"; +import Counter75 from "~/components/generated/counter75"; +import Counter76 from "~/components/generated/counter76"; +import Counter77 from "~/components/generated/counter77"; +import Counter78 from "~/components/generated/counter78"; +import Counter79 from "~/components/generated/counter79"; +import Counter80 from "~/components/generated/counter80"; +import Counter81 from "~/components/generated/counter81"; +import Counter82 from "~/components/generated/counter82"; +import Counter83 from "~/components/generated/counter83"; +import Counter84 from "~/components/generated/counter84"; +import Counter85 from "~/components/generated/counter85"; +import Counter86 from "~/components/generated/counter86"; +import Counter87 from "~/components/generated/counter87"; +import Counter88 from "~/components/generated/counter88"; +import Counter89 from "~/components/generated/counter89"; +import Counter90 from "~/components/generated/counter90"; +import Counter91 from "~/components/generated/counter91"; +import Counter92 from "~/components/generated/counter92"; +import Counter93 from "~/components/generated/counter93"; +import Counter94 from "~/components/generated/counter94"; +import Counter95 from "~/components/generated/counter95"; +import Counter96 from "~/components/generated/counter96"; +import Counter97 from "~/components/generated/counter97"; +import Counter98 from "~/components/generated/counter98"; +import Counter99 from "~/components/generated/counter99"; +import Counter100 from "~/components/generated/counter100"; +import ShowDynamic from "~/components/generated/show-dynamic"; + +export default component$(() => { + return ( +
+

Fallback

+

+ This page has 100 counters. Each counter is a separate component that is + preloaded. You can click on the "Say what?" button to see a reprio of + the say-what bundle and its transitive dependencies. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + console.log("visible below fold")} + > + Home + +
+ ); +}); diff --git a/starters/apps/preloader-test/src/routes/layout.tsx b/starters/apps/preloader-test/src/routes/layout.tsx index bf44e47e9d8..124bc4937c0 100644 --- a/starters/apps/preloader-test/src/routes/layout.tsx +++ b/starters/apps/preloader-test/src/routes/layout.tsx @@ -65,14 +65,14 @@ export default component$(() => {