Last active
November 20, 2022 11:18
-
-
Save reyronald/924b2449d732701666692aa0c6e09ffa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { BrowserRouter, Redirect } from "react-router-dom"; | |
import { CompatRouter, Routes, Route } from "react-router-dom-v5-compat"; | |
import { Internal1 } from "./Internal1"; | |
import { Loadable } from "./Loadable"; | |
const Loading = () => ( | |
<div style={{ width: "100%", height: "100vh", background: "red" }}>Loading</div> | |
); | |
const InternalsPack = Loadable( | |
// factory | |
() => import("./Internals.Bundle"), | |
{ | |
fallback: <Loading />, | |
}, | |
); | |
const Internal2 = InternalsPack((bundle) => bundle.Internal2); | |
const Internal3 = InternalsPack((bundle) => bundle.Internal3); | |
// Or... | |
// const factory = () => import("./Internals.Bundle"); | |
// const Internal2 = React.lazy(lazyBundle(factory, (b) => b.Internal2)); | |
// const Internal3 = React.lazy(lazyBundle(factory, (b) => b.Internal3)); | |
const Internal4 = React.lazy(() => import("./Internal4")); | |
export const AppRouterExperiment = () => { | |
return ( | |
<BrowserRouter> | |
<CompatRouter> | |
<AppRoutes /> | |
</CompatRouter> | |
</BrowserRouter> | |
); | |
}; | |
const AppRoutes = () => { | |
return ( | |
<Routes> | |
<Route path={"/internal/1"} element={<Internal1 />} /> | |
<Route path={"/internal/2"} element={<Internal2 name="Ronald" />} /> | |
<Route path={"/internal/3"} element={<Internal3 />} /> | |
<Route path={"/internal/4"} element={<Internal4 />} /> | |
<Route path="*" element={<Redirect to={"/internal/1"} />} /> | |
</Routes> | |
); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function lazyBundle<T, C extends ComponentType<any>>( | |
factory: () => Promise<{ default: T }>, | |
getModule: (bundle: T) => C, | |
) { | |
return async () => { | |
const bundle = await factory(); | |
const component = getModule(bundle.default); | |
return { default: component }; | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import type { ComponentType, ReactElement } from "react"; | |
const _cache = new WeakMap< | |
() => Promise<{ default: any }>, | |
{ | |
default: any; | |
} | |
>(); | |
export function Loadable<T>( | |
importBundle: () => Promise<{ default: T }>, | |
options: { | |
fallback?: ReactElement | null; | |
} = { | |
fallback: null, | |
}, | |
) { | |
return <C extends ComponentType<any>>(getComponent: (bundle: T) => C) => { | |
function LazyComponent(props: any) { | |
const [Component, setComponent] = React.useState<C | undefined>(() => { | |
const bundle = _cache.get(importBundle); | |
if (bundle) { | |
return getComponent(bundle.default); | |
} | |
}); | |
// eslint-disable-next-line use-encapsulation/prefer-custom-hooks -- . | |
React.useEffect(() => { | |
async function fetch() { | |
const bundle = await importBundle(); | |
_cache.set(importBundle, bundle); | |
const component = getComponent(bundle.default); | |
setComponent(() => component); | |
} | |
if (!Component) { | |
void fetch(); | |
} | |
}, [Component]); | |
if (!Component) { | |
return options.fallback || null; | |
} | |
return <Component {...props} />; | |
} | |
LazyComponent.displayName = `LazyComponent`; | |
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- . | |
return LazyComponent as C; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment