aboutsummaryrefslogtreecommitdiff
path: root/demos/hello-next/bun-framework-next/route-loader.ts
diff options
context:
space:
mode:
Diffstat (limited to 'demos/hello-next/bun-framework-next/route-loader.ts')
-rw-r--r--demos/hello-next/bun-framework-next/route-loader.ts395
1 files changed, 0 insertions, 395 deletions
diff --git a/demos/hello-next/bun-framework-next/route-loader.ts b/demos/hello-next/bun-framework-next/route-loader.ts
deleted file mode 100644
index 75012f82d..000000000
--- a/demos/hello-next/bun-framework-next/route-loader.ts
+++ /dev/null
@@ -1,395 +0,0 @@
-<<<<<<< Updated upstream
-import { ComponentType } from "react";
-// import { ClientBuildManifest } from "../build/webpack/plugins/build-manifest-plugin";
-import getAssetPathFromRoute from "next/dist/shared/lib/router/utils/get-asset-path-from-route";
-// import { requestIdleCallback } from "./request-idle-callback";
-
-const requestIdleCallback = window.requestAnimationFrame;
-
-// 3.8s was arbitrarily chosen as it's what https://web.dev/interactive
-// considers as "Good" time-to-interactive. We must assume something went
-// wrong beyond this point, and then fall-back to a full page transition to
-// show the user something of value.
-const MS_MAX_IDLE_DELAY = 3800;
-
-declare global {
- interface Window {
- __BUILD_MANIFEST?: ClientBuildManifest;
- __BUILD_MANIFEST_CB?: Function;
- }
-}
-
-export interface LoadedEntrypointSuccess {
- component: ComponentType;
- exports: any;
-}
-export interface LoadedEntrypointFailure {
- error: unknown;
-}
-export type RouteEntrypoint = LoadedEntrypointSuccess | LoadedEntrypointFailure;
-
-export interface RouteStyleSheet {
- href: string;
- content: string;
-}
-
-export interface LoadedRouteSuccess extends LoadedEntrypointSuccess {
- styles: RouteStyleSheet[];
-}
-export interface LoadedRouteFailure {
- error: unknown;
-}
-export type RouteLoaderEntry = LoadedRouteSuccess | LoadedRouteFailure;
-
-export type Future<V> = {
- resolve: (entrypoint: V) => void;
- future: Promise<V>;
-};
-function withFuture<T>(
- key: string,
- map: Map<string, Future<T> | T>,
- generator?: () => Promise<T>
-): Promise<T> {
- let entry: Future<T> | T | undefined = map.get(key);
- console.log({ entry });
- if (entry) {
- if ("future" in entry) {
- return entry.future;
- }
- return Promise.resolve(entry);
- }
-
- let resolver: (entrypoint: T) => void;
- const prom: Promise<T> = new Promise<T>((resolve) => {
- resolver = resolve;
- });
- map.set(key, (entry = { resolve: resolver!, future: prom }));
-
- return generator
- ? // eslint-disable-next-line no-sequences
- generator().then((value) => (resolver(value), value))
- : prom;
-}
-
-export interface RouteLoader {
- whenEntrypoint(route: string): Promise<RouteEntrypoint>;
- onEntrypoint(route: string, execute: () => unknown): void;
- loadRoute(route: string, prefetch?: boolean): Promise<RouteLoaderEntry>;
- prefetch(route: string): Promise<void>;
-}
-
-function hasPrefetch(link?: HTMLLinkElement): boolean {
- try {
- link = document.createElement("link");
- return (
- // detect IE11 since it supports prefetch but isn't detected
- // with relList.support
- (!!window.MSInputMethodContext && !!(document as any).documentMode) ||
- link.relList.supports("prefetch")
- );
- } catch {
- return false;
- }
-}
-
-const canPrefetch: boolean = hasPrefetch();
-
-function prefetchViaDom(
- href: string,
- as: string,
- link?: HTMLLinkElement
-): Promise<any> {
- return new Promise<void>((res, rej) => {
- if (document.querySelector(`link[rel="prefetch"][href^="${href}"]`)) {
- return res();
- }
-
- link = document.createElement("link");
-
- // The order of property assignment here is intentional:
- if (as) link!.as = as;
- link!.rel = `prefetch`;
- link!.crossOrigin = process.env.__NEXT_CROSS_ORIGIN!;
- link!.onload = res as any;
- link!.onerror = rej;
-
- // `href` should always be last:
- link!.href = href;
-
- document.head.appendChild(link);
- });
-}
-
-const ASSET_LOAD_ERROR = Symbol("ASSET_LOAD_ERROR");
-// TODO: unexport
-export function markAssetError(err: Error): Error {
- return Object.defineProperty(err, ASSET_LOAD_ERROR, {});
-}
-
-export function isAssetError(err?: Error): boolean | undefined {
- return err && ASSET_LOAD_ERROR in err;
-}
-
-function appendScript(
- src: string,
- script?: HTMLScriptElement
-): Promise<unknown> {
- return new Promise((resolve, reject) => {
- script = document.createElement("script");
-
- // The order of property assignment here is intentional.
- // 1. Setup success/failure hooks in case the browser synchronously
- // executes when `src` is set.
- script.onload = resolve;
- script.onerror = () =>
- reject(markAssetError(new Error(`Failed to load script: ${src}`)));
-
- // Bun: Add type module so we can utilize import/export
- script.type = "module";
-
- // 2. Configure the cross-origin attribute before setting `src` in case the
- // browser begins to fetch.
- script.crossOrigin = process.env.__NEXT_CROSS_ORIGIN!;
-
- // 3. Finally, set the source and inject into the DOM in case the child
- // must be appended for fetching to start.
- script.src = src;
- document.body.appendChild(script);
- });
-}
-
-// We wait for pages to be built in dev before we start the route transition
-// timeout to prevent an un-necessary hard navigation in development.
-let devBuildPromise: Promise<void> | undefined;
-let devBuildResolve: (() => void) | undefined;
-
-if (process.env.NODE_ENV === "development") {
- // const { addMessageListener } = require("./dev/error-overlay/eventsource");
- // addMessageListener((event: any) => {
- // // This is the heartbeat event
- // if (event.data === "\uD83D\uDC93") {
- // return;
- // }
- // const obj =
- // typeof event === "string" ? { action: event } : JSON.parse(event.data);
- // switch (obj.action) {
- // case "built":
- // case "sync":
- // if (devBuildResolve) {
- // devBuildResolve();
- // devBuildResolve = undefined;
- // }
- // break;
- // default:
- // break;
- // }
- // });
-}
-
-// Resolve a promise that times out after given amount of milliseconds.
-function resolvePromiseWithTimeout<T>(
- p: Promise<T>,
- ms: number,
- err: Error
-): Promise<T> {
- return new Promise((resolve, reject) => {
- let cancelled = false;
-
- p.then((r) => {
- // Resolved, cancel the timeout
- cancelled = true;
- resolve(r);
- }).catch(reject);
-
- // We wrap these checks separately for better dead-code elimination in
- // production bundles.
- if (process.env.NODE_ENV === "development") {
- (devBuildPromise || Promise.resolve()).then(() => {
- requestIdleCallback(() =>
- setTimeout(() => {
- if (!cancelled) {
- reject(err);
- }
- }, ms)
- );
- });
- }
-
- if (process.env.NODE_ENV !== "development") {
- requestIdleCallback(() =>
- setTimeout(() => {
- if (!cancelled) {
- reject(err);
- }
- }, ms)
- );
- }
- });
-}
-
-interface RouteFiles {
- scripts: string[];
- css: string[];
-}
-function getFilesForRoute(
- assetPrefix: string,
- route: string
-): Promise<RouteFiles> {
- return Promise.resolve({
- scripts: [
- encodeURI(
- globalThis.__NEXT_DATA.pages[route].filter((k) => !k.endsWith(".css"))
- ),
- ],
- // Styles are handled by `style-loader` in development:
- css: [],
- });
-}
-
-export default function createRouteLoader(assetPrefix: string): RouteLoader {
- const entrypoints: Map<string, Future<RouteEntrypoint> | RouteEntrypoint> =
- new Map();
- const loadedScripts: Map<string, Promise<unknown>> = new Map();
- const styleSheets: Map<string, Promise<RouteStyleSheet>> = new Map();
- const routes: Map<string, Future<RouteLoaderEntry> | RouteLoaderEntry> =
- new Map();
-
- function maybeExecuteScript(src: string): Promise<unknown> {
- debugger;
-
- let prom: Promise<unknown> | undefined = loadedScripts.get(src);
- if (prom) {
- return prom;
- }
-
- // Skip executing script if it's already in the DOM:
- if (document.querySelector(`script[src^="${src}"]`)) {
- return Promise.resolve();
- }
-
- loadedScripts.set(src, (prom = appendScript(src)));
- return prom;
- }
-
- function fetchStyleSheet(href: string): Promise<RouteStyleSheet> {
- let prom: Promise<RouteStyleSheet> | undefined = styleSheets.get(href);
- if (prom) {
- return prom;
- }
-
- styleSheets.set(
- href,
- (prom = fetch(href)
- .then((res) => {
- if (!res.ok) {
- throw new Error(`Failed to load stylesheet: ${href}`);
- }
- return res.text().then((text) => ({ href: href, content: text }));
- })
- .catch((err) => {
- throw markAssetError(err);
- }))
- );
- return prom;
- }
-
- return {
- whenEntrypoint(route: string) {
- return withFuture(route, entrypoints);
- },
- onEntrypoint(route: string, execute: () => unknown) {
- Promise.resolve(execute)
- .then((fn) => fn())
- .then(
- (exports: any) => ({
- component: (exports && exports.default) || exports,
- exports: exports,
- }),
- (err) => ({ error: err })
- )
- .then((input: RouteEntrypoint) => {
- const old = entrypoints.get(route);
- entrypoints.set(route, input);
- if (old && "resolve" in old) old.resolve(input);
- });
- },
- loadRoute(route: string, prefetch?: boolean) {
- return withFuture<RouteLoaderEntry>(route, routes, () => {
- if (process.env.NODE_ENV === "development") {
- devBuildPromise = new Promise<void>((resolve) => {
- devBuildResolve = resolve;
- });
- }
- debugger;
- return resolvePromiseWithTimeout(
- getFilesForRoute(assetPrefix, route)
- .then(({ scripts, css }) => {
- return Promise.all([
- entrypoints.has(route)
- ? []
- : Promise.all(scripts.map(maybeExecuteScript)),
- Promise.all(css.map(fetchStyleSheet)),
- ] as const);
- })
- .then((res) => {
- debugger;
- console.log({ res });
- return this.whenEntrypoint(route).then((entrypoint) => {
- debugger;
- return {
- entrypoint,
- styles: res[1],
- };
- });
- }),
- MS_MAX_IDLE_DELAY,
- markAssetError(new Error(`Route did not complete loading: ${route}`))
- )
- .then(({ entrypoint, styles }) => {
- debugger;
- const res: RouteLoaderEntry = Object.assign<
- { styles: RouteStyleSheet[] },
- RouteEntrypoint
- >({ styles: styles! }, entrypoint);
- return "error" in entrypoint ? entrypoint : res;
- })
- .catch((err) => {
- if (prefetch) {
- // we don't want to cache errors during prefetch
- throw err;
- }
- return { error: err };
- });
- });
- },
- prefetch(route: string): Promise<void> {
- // https://github.com/GoogleChromeLabs/quicklink/blob/453a661fa1fa940e2d2e044452398e38c67a98fb/src/index.mjs#L115-L118
- // License: Apache 2.0
- let cn;
- if ((cn = (navigator as any).connection)) {
- // Don't prefetch if using 2G or if Save-Data is enabled.
- if (cn.saveData || /2g/.test(cn.effectiveType))
- return Promise.resolve();
- }
- return getFilesForRoute(assetPrefix, route)
- .then((output) =>
- Promise.all(
- canPrefetch
- ? output.scripts.map((script) => prefetchViaDom(script, "script"))
- : []
- )
- )
- .then(() => {
- requestIdleCallback(() =>
- this.loadRoute(route, true).catch(() => {})
- );
- })
- .catch(
- // swallow prefetch errors
- () => {}
- );
- },
- };
-}
-=======
->>>>>>> Stashed changes