diff options
-rw-r--r-- | packages/bun-framework-next/client.development.tsx | 59 | ||||
-rw-r--r-- | packages/bun-framework-next/fallback.development.tsx | 3 | ||||
-rw-r--r-- | packages/bun-framework-next/package.json | 3 | ||||
-rw-r--r-- | packages/bun-framework-next/page-loader.ts | 16 | ||||
-rw-r--r-- | packages/bun-framework-next/server-polyfills.tsx | 12 | ||||
-rw-r--r-- | packages/bun-framework-next/server.development.tsx | 1 | ||||
-rw-r--r-- | pnpm-lock.yaml | 31 |
7 files changed, 93 insertions, 32 deletions
diff --git a/packages/bun-framework-next/client.development.tsx b/packages/bun-framework-next/client.development.tsx index f3d8d39e5..bf03af289 100644 --- a/packages/bun-framework-next/client.development.tsx +++ b/packages/bun-framework-next/client.development.tsx @@ -1,10 +1,20 @@ +/// <reference types="react-dom/experimental" /> + globalThis.global = globalThis; globalThis.Bun_disableCSSImports = true; import * as React from "react"; + var onlyChildPolyfill = React.Children.only; -React.Children.only = function (children) { - if (children && typeof children === "object" && children.length == 1) { + +React.Children.only = function only( + children: React.ReactNode | React.ReactNode[] +) { + if ( + children && + typeof children === "object" && + (children as any).length == 1 + ) { return onlyChildPolyfill(children[0]); } @@ -23,9 +33,7 @@ import Router, { PrivateRouteInfo, } from "next/dist/shared/lib/router/router"; -const App = NextApp; - -import * as NextRouteLoader from "next/dist/client/route-loader"; +import NextRouteLoader from "next/dist/client/route-loader"; import { isDynamicRoute } from "next/dist/shared/lib/router/utils/is-dynamic"; import { urlQueryToSearchParams, @@ -41,8 +49,11 @@ import { createRouter, makePublicRouterInstance, } from "next/dist/client/router"; + export const emitter: MittEmitter<string> = mitt(); +const App = NextApp; + declare global { interface Window { /* test fns */ @@ -102,7 +113,8 @@ type RenderRouteInfo = PrivateRouteInfo & { const nextDataTag = document.getElementById("__NEXT_DATA__"); -const data: typeof window["__NEXT_DATA__"] = nextDataTag +// pages is added at runtime and doesn't exist in Next types +const data: NEXT_DATA & { pages: Record<string, string[]> } = nextDataTag ? JSON.parse(document.getElementById("__NEXT_DATA__")!.textContent!) : nextDataFromBunData(); @@ -116,12 +128,14 @@ const { buildId, assetPrefix, runtimeConfig, + // Todo, revist this constant when supporting dynamic() dynamicIds, isFallback, locale, locales, domainLocales, isPreview, + pages, } = data; const prefix: string = assetPrefix || ""; @@ -138,24 +152,19 @@ if (hasBasePath(asPath)) { asPath = delBasePath(asPath); } -export const pageLoader: PageLoader = new PageLoader( - buildId, - prefix, - data.pages -); +export const pageLoader: PageLoader = new PageLoader(buildId, prefix, pages); const headManager: { mountedInstances: Set<unknown>; updateHead: (head: JSX.Element[]) => void; } = initHeadManager(); -const appElement: HTMLElement | null = document.getElementById("__next"); export let router: Router; -let CachedApp: AppComponent = App, - onPerfEntry: (metric: any) => void; -export default function boot(EntryPointNamespace, loader) { - _boot(EntryPointNamespace).then(() => {}, false); +let CachedApp: AppComponent = null; + +export default function boot(EntryPointNamespace) { + _boot(EntryPointNamespace, false); } class Container extends React.Component<{ @@ -274,7 +283,7 @@ let reactRoot: any = null; const USE_REACT_18 = "hydrateRoot" in ReactDOM; export async function _boot(EntryPointNamespace, isError) { - NextRouteLoader.default.getClientBuildManifest = () => Promise.resolve({}); + NextRouteLoader.getClientBuildManifest = () => Promise.resolve({}); const PageComponent = EntryPointNamespace.default; @@ -293,6 +302,7 @@ export async function _boot(EntryPointNamespace, isError) { if (appSrc) { const AppModule = await import(appSrc); + console.assert( AppModule.default, appSrc + " must have a default export'd React component" @@ -332,7 +342,9 @@ export async function _boot(EntryPointNamespace, isError) { }); globalThis.next.router = router; + const domEl = document.querySelector("#__next"); + const reactEl = ( <TopLevelRender App={CachedApp} @@ -361,9 +373,9 @@ export async function _boot(EntryPointNamespace, isError) { } } -function TopLevelRender({ App, Component, props, scroll }) { +function TopLevelRender({ App, Component, props }) { return ( - <AppContainer scroll={scroll}> + <AppContainer> <App Component={Component} {...props}></App> </AppContainer> ); @@ -381,18 +393,15 @@ export function render(props) { } export function renderError(e) { - const reactEl = ( - <AppContainer> - <App Component={<div>UH OH!!!!</div>} pageProps={data.props}></App> - </AppContainer> - ); + // TODO verify this works + const reactEl = <AppContainer>{null}</AppContainer>; if (USE_REACT_18) { if (!reactRoot) { const domEl = document.querySelector("#__next"); // Unlike with createRoot, you don't need a separate root.render() call here - reactRoot = ReactDOM.createRoot(domEl, reactEl); + reactRoot = ReactDOM.hydrateRoot(domEl, reactEl); } else { reactRoot.render(reactEl); } diff --git a/packages/bun-framework-next/fallback.development.tsx b/packages/bun-framework-next/fallback.development.tsx index 54d31d5f5..460b5e165 100644 --- a/packages/bun-framework-next/fallback.development.tsx +++ b/packages/bun-framework-next/fallback.development.tsx @@ -1,5 +1,5 @@ import { insertStyleSheet } from "./page-loader"; -import type { FallbackMessageContainer } from "../../../src/api/schema"; +import type { FallbackMessageContainer } from "../../src/api/schema"; var once = false; function insertNextHeadCount() { @@ -65,6 +65,7 @@ function renderFallback({ router }: FallbackMessageContainer) { } export default function render(props: FallbackMessageContainer) { + // @ts-expect-error bun:error.js is real return import("/bun:error.js").then(({ renderFallbackError }) => { return renderFallback(props).then( () => { diff --git a/packages/bun-framework-next/package.json b/packages/bun-framework-next/package.json index b07199615..ea459412a 100644 --- a/packages/bun-framework-next/package.json +++ b/packages/bun-framework-next/package.json @@ -11,12 +11,15 @@ "author": "", "license": "MIT", "dependencies": { + "bun-framework-next": "^12.0.4", "react-is": "^17.0.2" }, "peerDependencies": { "next": "^12.0.0" }, "devDependencies": { + "@types/react": "^17.0.34", + "@types/react-dom": "^17.0.11", "next": "^12.0.0", "react-refresh": "^0.10.0", "typescript": "^4.4.4" diff --git a/packages/bun-framework-next/page-loader.ts b/packages/bun-framework-next/page-loader.ts index 2a8b402ad..3b31387d8 100644 --- a/packages/bun-framework-next/page-loader.ts +++ b/packages/bun-framework-next/page-loader.ts @@ -1,4 +1,6 @@ -import NextPageLoader from "next/dist/client/page-loader"; +import NextPageLoader, { + GoodPageCache as NextGoodPageCache, +} from "next/dist/client/page-loader"; import getAssetPathFromRoute from "next/dist/shared/lib/router/utils/get-asset-path-from-route"; export function insertStyleSheet(url: string) { @@ -10,8 +12,9 @@ export function insertStyleSheet(url: string) { const link = document.createElement("link"); link.rel = "stylesheet"; - link.onload = () => resolve(); - link.onerror = () => reject(); + // marking this resolve as void seems to break other things + link.onload = resolve; + link.onerror = reject; link.href = url; @@ -19,6 +22,11 @@ export function insertStyleSheet(url: string) { }); } +interface GoodPageCache extends NextGoodPageCache { + __N_SSG: boolean; + __N_SSP: boolean; +} + export default class PageLoader extends NextPageLoader { constructor(_, __, pages) { super(_, __); @@ -70,7 +78,7 @@ export default class PageLoader extends NextPageLoader { }; prefetch() { - return Promise.resolve({}); + return Promise.resolve(); } async loadPage(route: string): Promise<GoodPageCache> { diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index d34c08fc5..8942154b7 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -7,15 +7,23 @@ globalThis.Buffer = Buffer; import * as React from "react"; class URL { - constructor(base, source) { + pathname: string; + href: string; + + constructor(base: string, source: string) { this.pathname = source; this.href = base + source; } } + var onlyChildPolyfill = React.Children.only; React.Children.only = function (children) { - if (children && typeof children === "object" && children.length == 1) { + if ( + children && + typeof children === "object" && + (children as any).length == 1 + ) { return onlyChildPolyfill(children[0]); } diff --git a/packages/bun-framework-next/server.development.tsx b/packages/bun-framework-next/server.development.tsx index 96ba55812..fd2a7b620 100644 --- a/packages/bun-framework-next/server.development.tsx +++ b/packages/bun-framework-next/server.development.tsx @@ -1,6 +1,7 @@ import nextPackage from "next/package.json"; import "./server-polyfills"; import { render } from "./renderDocument"; +import { ResolveError } from "../../src/runtime/errors"; const { version } = nextPackage; if ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b96e023bc..4fa5982b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,6 +43,9 @@ importers: packages/bun-framework-next: specifiers: + '@types/react': ^17.0.34 + '@types/react-dom': ^17.0.11 + bun-framework-next: ^12.0.4 next: ^12.0.0 react-is: ^17.0.2 react-refresh: ^0.10.0 @@ -50,6 +53,8 @@ importers: dependencies: react-is: 17.0.2 devDependencies: + '@types/react': 17.0.34 + '@types/react-dom': 17.0.11 next: 12.0.3_react-dom@17.0.2+react@17.0.2 react-refresh: 0.10.0 typescript: 4.4.4 @@ -279,12 +284,34 @@ packages: /@types/node/16.11.4: resolution: {integrity: sha512-TMgXmy0v2xWyuCSCJM6NCna2snndD8yvQF67J29ipdzMcsPa9u+o0tjF5+EQNdhcuZplYuouYqpc4zcd5I6amQ==} + /@types/prop-types/15.7.4: + resolution: {integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==} + dev: true + /@types/puppeteer/5.4.4: resolution: {integrity: sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q==} dependencies: '@types/node': 16.11.4 dev: true + /@types/react-dom/17.0.11: + resolution: {integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==} + dependencies: + '@types/react': 17.0.34 + dev: true + + /@types/react/17.0.34: + resolution: {integrity: sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg==} + dependencies: + '@types/prop-types': 15.7.4 + '@types/scheduler': 0.16.2 + csstype: 3.0.10 + dev: true + + /@types/scheduler/0.16.2: + resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} + dev: true + /@types/yauzl/2.9.2: resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} requiresBuild: true @@ -749,6 +776,10 @@ packages: postcss: 8.2.15 dev: true + /csstype/3.0.10: + resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} + dev: true + /data-uri-to-buffer/3.0.1: resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} engines: {node: '>= 6'} |