From 32056b5cb6717e08e86cf64990eb1d9109d378f7 Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Sat, 21 Mar 2026 18:03:36 +0100 Subject: [PATCH] Update HMR logic. Refresh on server props update. --- .../functions/bundler/grab-client-hydration-script.js | 6 +++--- dist/functions/server/server-post-build-fn.js | 8 ++++++++ .../web-pages/grab-web-page-hydration-script.js | 5 +++++ dist/types/index.d.ts | 10 ++++++++++ package.json | 2 +- src/functions/bundler/grab-client-hydration-script.ts | 11 +++++++---- src/functions/server/server-post-build-fn.ts | 11 +++++++++++ .../web-pages/grab-web-page-hydration-script.tsx | 7 +++++++ src/types/index.ts | 6 ++++++ 9 files changed, 58 insertions(+), 8 deletions(-) diff --git a/dist/functions/bundler/grab-client-hydration-script.js b/dist/functions/bundler/grab-client-hydration-script.js index dd0026a..d196be1 100644 --- a/dist/functions/bundler/grab-client-hydration-script.js +++ b/dist/functions/bundler/grab-client-hydration-script.js @@ -5,7 +5,7 @@ import AppNames from "../../utils/grab-app-names"; import grabConstants from "../../utils/grab-constants"; const { PAGES_DIR } = grabDirNames(); export default function grabClientHydrationScript({ page_local_path }) { - const { ClientRootElementIDName, ClientRootComponentWindowName } = grabConstants(); + const { ClientRootElementIDName, ClientRootComponentWindowName, ClientWindowPagePropsName, } = grabConstants(); const root_component_path = path.join(PAGES_DIR, `${AppNames["RootPagesComponentName"]}.tsx`); const does_root_exist = existsSync(root_component_path); let txt = ``; @@ -14,7 +14,7 @@ export default function grabClientHydrationScript({ page_local_path }) { txt += `import Root from "${root_component_path}";\n`; } txt += `import Page from "${page_local_path}";\n\n`; - txt += `const pageProps = window.__PAGE_PROPS__ || {};\n`; + txt += `const pageProps = window.${ClientWindowPagePropsName} || {};\n`; if (does_root_exist) { txt += `const component = \n`; } @@ -29,7 +29,7 @@ export default function grabClientHydrationScript({ page_local_path }) { txt += ` } });\n\n`; txt += ` window.${ClientRootComponentWindowName} = root;\n`; txt += ` window.__BUNEXT_RERENDER__ = (NewPage) => {\n`; - txt += ` const props = window.__PAGE_PROPS__ || {};\n`; + txt += ` const props = window.${ClientWindowPagePropsName} || {};\n`; txt += ` root.render();\n`; txt += ` };\n`; txt += `}\n`; diff --git a/dist/functions/server/server-post-build-fn.js b/dist/functions/server/server-post-build-fn.js index 23496cc..d27b83f 100644 --- a/dist/functions/server/server-post-build-fn.js +++ b/dist/functions/server/server-post-build-fn.js @@ -1,4 +1,5 @@ import _ from "lodash"; +import grabPageComponent from "./web-pages/grab-page-component"; export default async function serverPostBuildFn({ artifacts }) { if (!global.IS_FIRST_BUNDLE_READY) { global.IS_FIRST_BUNDLE_READY = true; @@ -9,6 +10,10 @@ export default async function serverPostBuildFn({ artifacts }) { for (let i = 0; i < global.HMR_CONTROLLERS.length; i++) { const controller = global.HMR_CONTROLLERS[i]; const target_artifact = artifacts.find((a) => controller.target_map?.local_path == a.local_path); + const mock_req = new Request(controller.page_url); + const { serverRes } = await grabPageComponent({ + req: mock_req, + }); const final_artifact = { ..._.omit(controller, ["controller"]), target_map: target_artifact, @@ -16,6 +21,9 @@ export default async function serverPostBuildFn({ artifacts }) { if (!target_artifact) { delete final_artifact.target_map; } + if (serverRes) { + final_artifact.page_props = serverRes; + } try { controller.controller.enqueue(`event: update\ndata: ${JSON.stringify(final_artifact)}\n\n`); } diff --git a/dist/functions/server/web-pages/grab-web-page-hydration-script.js b/dist/functions/server/web-pages/grab-web-page-hydration-script.js index e0e7c96..92ddc41 100644 --- a/dist/functions/server/web-pages/grab-web-page-hydration-script.js +++ b/dist/functions/server/web-pages/grab-web-page-hydration-script.js @@ -1,5 +1,7 @@ import { AppData } from "../../../data/app-data"; +import grabConstants from "../../../utils/grab-constants"; export default async function (params) { + const { ClientWindowPagePropsName } = grabConstants(); let script = ""; script += `console.log(\`Development Environment\`);\n\n`; script += `const _ce = console.error.bind(console);\n`; @@ -28,6 +30,9 @@ export default async function (params) { script += ` document.getElementById("__bunext_error_overlay")?.remove();\n`; script += ` const data = JSON.parse(event.data);\n`; // script += ` console.log("data", data);\n`; + script += ` if (data.page_props) {\n`; + script += ` window.${ClientWindowPagePropsName} = data.page_props\n`; + script += ` }\n`; script += ` const oldCSSLink = document.querySelector('link[rel="stylesheet"]');\n`; script += ` if (data.target_map.css_path) {\n`; script += ` const newLink = document.createElement("link");\n`; diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts index d646c3e..3e28009 100644 --- a/dist/types/index.d.ts +++ b/dist/types/index.d.ts @@ -210,6 +210,15 @@ export type BunextPageModuleServerReturn = BunextPageModuleServerReturn; export type BunextPageModuleServerReturnURLObject = URL & {}; export type BunextPageModuleServerRedirect = { destination: string; @@ -254,6 +263,7 @@ export type GlobalHMRControllerObject = { controller: ReadableStreamDefaultController; page_url: string; target_map?: BundlerCTXMap; + page_props?: any; }; export type BunextCacheFileMeta = { date_created: number; diff --git a/package.json b/package.json index 987fcfe..175e2f9 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ ], "scripts": { "dev": "tsc --watch", - "git:push": "tsc --noEmit && tsc && git add . && git commit -m 'Update dependencies.' && git push", + "git:push": "tsc --noEmit && tsc && git add . && git commit -m 'Update HMR logic. Refresh on server props update.' && git push", "compile": "bun build ./src/commands/index.ts --compile --outfile bin/bunext --minify", "build": "tsc", "test": "bun test --max-concurrency=1" diff --git a/src/functions/bundler/grab-client-hydration-script.ts b/src/functions/bundler/grab-client-hydration-script.ts index 6d54049..ba59199 100644 --- a/src/functions/bundler/grab-client-hydration-script.ts +++ b/src/functions/bundler/grab-client-hydration-script.ts @@ -11,8 +11,11 @@ type Params = { }; export default function grabClientHydrationScript({ page_local_path }: Params) { - const { ClientRootElementIDName, ClientRootComponentWindowName } = - grabConstants(); + const { + ClientRootElementIDName, + ClientRootComponentWindowName, + ClientWindowPagePropsName, + } = grabConstants(); const root_component_path = path.join( PAGES_DIR, @@ -28,7 +31,7 @@ export default function grabClientHydrationScript({ page_local_path }: Params) { txt += `import Root from "${root_component_path}";\n`; } txt += `import Page from "${page_local_path}";\n\n`; - txt += `const pageProps = window.__PAGE_PROPS__ || {};\n`; + txt += `const pageProps = window.${ClientWindowPagePropsName} || {};\n`; if (does_root_exist) { txt += `const component = \n`; @@ -45,7 +48,7 @@ export default function grabClientHydrationScript({ page_local_path }: Params) { txt += ` window.${ClientRootComponentWindowName} = root;\n`; txt += ` window.__BUNEXT_RERENDER__ = (NewPage) => {\n`; - txt += ` const props = window.__PAGE_PROPS__ || {};\n`; + txt += ` const props = window.${ClientWindowPagePropsName} || {};\n`; txt += ` root.render();\n`; txt += ` };\n`; txt += `}\n`; diff --git a/src/functions/server/server-post-build-fn.ts b/src/functions/server/server-post-build-fn.ts index 10c4491..e24c388 100644 --- a/src/functions/server/server-post-build-fn.ts +++ b/src/functions/server/server-post-build-fn.ts @@ -1,5 +1,6 @@ import _ from "lodash"; import type { BundlerCTXMap, GlobalHMRControllerObject } from "../../types"; +import grabPageComponent from "./web-pages/grab-page-component"; type Params = { artifacts: BundlerCTXMap[]; @@ -21,6 +22,12 @@ export default async function serverPostBuildFn({ artifacts }: Params) { (a) => controller.target_map?.local_path == a.local_path, ); + const mock_req = new Request(controller.page_url); + + const { serverRes } = await grabPageComponent({ + req: mock_req, + }); + const final_artifact: Omit = { ..._.omit(controller, ["controller"]), target_map: target_artifact, @@ -30,6 +37,10 @@ export default async function serverPostBuildFn({ artifacts }: Params) { delete final_artifact.target_map; } + if (serverRes) { + final_artifact.page_props = serverRes; + } + try { controller.controller.enqueue( `event: update\ndata: ${JSON.stringify(final_artifact)}\n\n`, diff --git a/src/functions/server/web-pages/grab-web-page-hydration-script.tsx b/src/functions/server/web-pages/grab-web-page-hydration-script.tsx index 4bca438..4727345 100644 --- a/src/functions/server/web-pages/grab-web-page-hydration-script.tsx +++ b/src/functions/server/web-pages/grab-web-page-hydration-script.tsx @@ -1,11 +1,14 @@ import type { BundlerCTXMap } from "../../../types"; import { AppData } from "../../../data/app-data"; +import grabConstants from "../../../utils/grab-constants"; type Params = { bundledMap?: BundlerCTXMap; }; export default async function (params?: Params) { + const { ClientWindowPagePropsName } = grabConstants(); + let script = ""; script += `console.log(\`Development Environment\`);\n\n`; @@ -38,6 +41,10 @@ export default async function (params?: Params) { script += ` const data = JSON.parse(event.data);\n`; // script += ` console.log("data", data);\n`; + script += ` if (data.page_props) {\n`; + script += ` window.${ClientWindowPagePropsName} = data.page_props\n`; + script += ` }\n`; + script += ` const oldCSSLink = document.querySelector('link[rel="stylesheet"]');\n`; script += ` if (data.target_map.css_path) {\n`; diff --git a/src/types/index.ts b/src/types/index.ts index 5a1f9ef..3d42085 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -229,6 +229,11 @@ export type BunextPageModuleServerReturn< url?: BunextPageModuleServerReturnURLObject; }; +export type BunextPageProps< + T extends { [k: string]: any } = { [k: string]: any }, + Q extends { [k: string]: any } = { [k: string]: any }, +> = BunextPageModuleServerReturn; + export type BunextPageModuleServerReturnURLObject = URL & {}; export type BunextPageModuleServerRedirect = { @@ -280,6 +285,7 @@ export type GlobalHMRControllerObject = { controller: ReadableStreamDefaultController; page_url: string; target_map?: BundlerCTXMap; + page_props?: any; }; export type BunextCacheFileMeta = {