From a9cd51d71c7b7fb6a33d5e0e18c1628ebbc8b957 Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Mon, 20 Jul 2026 20:54:39 +0100 Subject: [PATCH] Bugfix: update stale HMR after fixed errors --- .../plugins/esbuild-ctx-artifact-tracker.js | 24 ++++++++---------- dist/functions/bunext-init.js | 4 +-- dist/functions/server/full-rebuild.js | 4 +-- dist/functions/server/server-post-build-fn.js | 20 +++++++-------- .../grab-page-bundled-react-component.js | 4 ++- .../grab-page-combined-server-res.js | 6 +++++ package.json | 2 +- .../bundler/build-on-start-error-handler.ts | 4 +-- .../plugins/esbuild-ctx-artifact-tracker.ts | 25 ++++++++----------- src/functions/bunext-init.ts | 4 +-- src/functions/server/full-rebuild.ts | 4 +-- src/functions/server/server-post-build-fn.ts | 20 +++++++-------- .../grab-page-bundled-react-component.tsx | 7 ++++-- .../grab-page-combined-server-res.ts | 6 +++++ 14 files changed, 71 insertions(+), 63 deletions(-) diff --git a/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js b/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js index e65a4a6..de3786a 100644 --- a/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js +++ b/dist/functions/bundler/plugins/esbuild-ctx-artifact-tracker.js @@ -56,20 +56,13 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn, _.merge(global.BUNDLER_CTX_MAP[artifact.local_path], artifact); } } - try { - await post_build_fn?.({ artifacts }); - } - catch (error) { - log.error(`Post-build Error: ${error}`); - } } const elapsed = (performance.now() - build_start).toFixed(0); log.success(`[Built] in ${elapsed}ms`); - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; global.MAIN_CTX_BUILD_STARTS = 0; global.BUNDLER_CTX_DISPOSED = false; const does_error_file_exist = existsSync(BUNX_BUNDLER_ERROR_EXIT_FILE); + // SSR must finish before HMR so server props are fresh if (build_only) { try { await pagesSSRBundler(); @@ -92,12 +85,17 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn, catch (error) { log.error(`SSR Bundler Error: ${error}`); } + if (artifacts?.[0] && artifacts.length > 0) { + try { + await post_build_fn?.({ artifacts }); + } + catch (error) { + log.error(`Post-build Error: ${error}`); + } + } } - // if (global.SSR_BUNDLER_CTX) { - // global.SSR_BUNDLER_CTX.rebuild(); - // } else { - // pagesSSRContextBundler(); - // } + global.RECOMPILING = false; + global.IS_SERVER_COMPONENT = false; }); }, }; diff --git a/dist/functions/bunext-init.js b/dist/functions/bunext-init.js index a07a2cd..607c6d3 100644 --- a/dist/functions/bunext-init.js +++ b/dist/functions/bunext-init.js @@ -40,8 +40,8 @@ export default async function bunextInit(params) { else if (is_dev) { log.build(`Building Modules ...`); await allPagesESBuildContextBundler({ - post_build_fn: () => { - serverPostBuildFn(); + post_build_fn: async () => { + await serverPostBuildFn(); }, }); watcherEsbuildCTX(); diff --git a/dist/functions/server/full-rebuild.js b/dist/functions/server/full-rebuild.js index b2aeffb..234c2f8 100644 --- a/dist/functions/server/full-rebuild.js +++ b/dist/functions/server/full-rebuild.js @@ -18,8 +18,8 @@ export default async function fullRebuild(params) { } catch (error) { } await allPagesESBuildContextBundler({ - post_build_fn: () => { - serverPostBuildFn(); + post_build_fn: async () => { + await serverPostBuildFn(); }, }); } diff --git a/dist/functions/server/server-post-build-fn.js b/dist/functions/server/server-post-build-fn.js index 6b909c0..6820461 100644 --- a/dist/functions/server/server-post-build-fn.js +++ b/dist/functions/server/server-post-build-fn.js @@ -43,17 +43,16 @@ export default async function serverPostBuildFn(params) { const mock_req = target_artifact.req_url ? new Request(target_artifact.req_url) : new Request(controller.page_url); - const page_component = global.IS_SERVER_COMPONENT - ? await grabPageComponent({ - req: mock_req, - return_server_res_only: true, - is_hydration: true, - }) - : {}; + // Always re-run server fns so fixed errors clear on the first HMR + const page_component = await grabPageComponent({ + req: mock_req, + return_server_res_only: true, + is_hydration: true, + }); if (page_component instanceof Response) { continue; } - const { serverRes } = page_component; + const { serverRes } = page_component || {}; const final_artifact = { ..._.omit(controller, ["controller"]), target_map: target_artifact, @@ -61,9 +60,8 @@ export default async function serverPostBuildFn(params) { if (!target_artifact) { delete final_artifact.target_map; } - if (serverRes) { - final_artifact.page_props = serverRes; - } + // Always replace so prior error props cannot linger + final_artifact.page_props = serverRes || {}; try { let final_data = {}; if (global.ROOT_FILE_UPDATED) { diff --git a/dist/functions/server/web-pages/grab-page-bundled-react-component.js b/dist/functions/server/web-pages/grab-page-bundled-react-component.js index b86cb1a..cc3fdad 100644 --- a/dist/functions/server/web-pages/grab-page-bundled-react-component.js +++ b/dist/functions/server/web-pages/grab-page-bundled-react-component.js @@ -8,7 +8,9 @@ const { ROOT_DIR } = grabDirNames(); export default async function grabPageBundledReactComponent({ file_path, return_tsx_only, }) { try { if (global.SSR_BUNDLER_CTX_MAP?.[file_path]) { - const mod = await import(path.join(ROOT_DIR, global.SSR_BUNDLER_CTX_MAP[file_path].path)); + const abs = path.join(ROOT_DIR, global.SSR_BUNDLER_CTX_MAP[file_path].path); + Loader.registry.delete(abs); + const mod = await import(`${abs}?t=${Date.now()}`); const Main = mod.default; return { component: Main }; } diff --git a/dist/functions/server/web-pages/grab-page-combined-server-res.js b/dist/functions/server/web-pages/grab-page-combined-server-res.js index cc8e4e9..dbdfbf1 100644 --- a/dist/functions/server/web-pages/grab-page-combined-server-res.js +++ b/dist/functions/server/web-pages/grab-page-combined-server-res.js @@ -16,6 +16,9 @@ export default async function grabPageCombinedServerRes({ file_path, debug, url, const final_root_server_path = root_server_ctx_map?.local_path ? path.join(ROOT_DIR, root_server_ctx_map.path) : root_server_file_path; + if (final_root_server_path) { + Loader.registry.delete(final_root_server_path); + } const root_server_module = final_root_server_path ? await import(`${final_root_server_path}?t=${now}`) : undefined; @@ -34,6 +37,9 @@ export default async function grabPageCombinedServerRes({ file_path, debug, url, const final_page_server_path = page_server_ctx?.local_path ? path.join(ROOT_DIR, page_server_ctx.path) : server_file_path; + if (final_page_server_path) { + Loader.registry.delete(final_page_server_path); + } const server_module = final_page_server_path ? await import(`${final_page_server_path}?t=${now}`) : undefined; diff --git a/package.json b/package.json index c083484..584af51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@moduletrace/bunext", - "version": "1.0.96", + "version": "1.0.97", "main": "dist/index.js", "module": "index.ts", "dependencies": { diff --git a/src/functions/bundler/build-on-start-error-handler.ts b/src/functions/bundler/build-on-start-error-handler.ts index eb58bc9..20513db 100644 --- a/src/functions/bundler/build-on-start-error-handler.ts +++ b/src/functions/bundler/build-on-start-error-handler.ts @@ -8,8 +8,8 @@ export default async function buildOnstartErrorHandler(params?: Params) { return; } - console.log(`Killing Bundler ...`); - console.log(`global.BUNDLER_CTX_DISPOSED`, global.BUNDLER_CTX_DISPOSED); + // console.log(`Killing Bundler ...`); + // console.log(`global.BUNDLER_CTX_DISPOSED`, global.BUNDLER_CTX_DISPOSED); global.BUNDLER_CTX_DISPOSED = true; diff --git a/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts b/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts index 09f71eb..c26dab9 100644 --- a/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts +++ b/src/functions/bundler/plugins/esbuild-ctx-artifact-tracker.ts @@ -97,20 +97,11 @@ export default function esbuildCTXArtifactTracker({ ); } } - - try { - await post_build_fn?.({ artifacts }); - } catch (error) { - log.error(`Post-build Error: ${error}`); - } } const elapsed = (performance.now() - build_start).toFixed(0); log.success(`[Built] in ${elapsed}ms`); - global.RECOMPILING = false; - global.IS_SERVER_COMPONENT = false; - global.MAIN_CTX_BUILD_STARTS = 0; global.BUNDLER_CTX_DISPOSED = false; @@ -118,6 +109,7 @@ export default function esbuildCTXArtifactTracker({ BUNX_BUNDLER_ERROR_EXIT_FILE, ); + // SSR must finish before HMR so server props are fresh if (build_only) { try { await pagesSSRBundler(); @@ -139,13 +131,18 @@ export default function esbuildCTXArtifactTracker({ } catch (error) { log.error(`SSR Bundler Error: ${error}`); } + + if (artifacts?.[0] && artifacts.length > 0) { + try { + await post_build_fn?.({ artifacts }); + } catch (error) { + log.error(`Post-build Error: ${error}`); + } + } } - // if (global.SSR_BUNDLER_CTX) { - // global.SSR_BUNDLER_CTX.rebuild(); - // } else { - // pagesSSRContextBundler(); - // } + global.RECOMPILING = false; + global.IS_SERVER_COMPONENT = false; }); }, }; diff --git a/src/functions/bunext-init.ts b/src/functions/bunext-init.ts index 676cc09..bcac588 100644 --- a/src/functions/bunext-init.ts +++ b/src/functions/bunext-init.ts @@ -98,8 +98,8 @@ export default async function bunextInit(params?: Params) { } else if (is_dev) { log.build(`Building Modules ...`); await allPagesESBuildContextBundler({ - post_build_fn: () => { - serverPostBuildFn(); + post_build_fn: async () => { + await serverPostBuildFn(); }, }); watcherEsbuildCTX(); diff --git a/src/functions/server/full-rebuild.ts b/src/functions/server/full-rebuild.ts index d17e854..cd318a9 100644 --- a/src/functions/server/full-rebuild.ts +++ b/src/functions/server/full-rebuild.ts @@ -24,8 +24,8 @@ export default async function fullRebuild(params?: { msg?: string }) { } catch (error) {} await allPagesESBuildContextBundler({ - post_build_fn: () => { - serverPostBuildFn(); + post_build_fn: async () => { + await serverPostBuildFn(); }, }); } catch (error: any) { diff --git a/src/functions/server/server-post-build-fn.ts b/src/functions/server/server-post-build-fn.ts index 7cf56aa..bfdfd85 100644 --- a/src/functions/server/server-post-build-fn.ts +++ b/src/functions/server/server-post-build-fn.ts @@ -57,19 +57,18 @@ export default async function serverPostBuildFn(params?: Params) { ? new Request(target_artifact.req_url) : new Request(controller.page_url); - const page_component = global.IS_SERVER_COMPONENT - ? await grabPageComponent({ - req: mock_req, - return_server_res_only: true, - is_hydration: true, - }) - : {}; + // Always re-run server fns so fixed errors clear on the first HMR + const page_component = await grabPageComponent({ + req: mock_req, + return_server_res_only: true, + is_hydration: true, + }); if (page_component instanceof Response) { continue; } - const { serverRes } = page_component; + const { serverRes } = page_component || {}; const final_artifact: Omit = { ..._.omit(controller, ["controller"]), @@ -80,9 +79,8 @@ export default async function serverPostBuildFn(params?: Params) { delete final_artifact.target_map; } - if (serverRes) { - final_artifact.page_props = serverRes; - } + // Always replace so prior error props cannot linger + final_artifact.page_props = serverRes || {}; try { let final_data: { [k: string]: any } = {}; diff --git a/src/functions/server/web-pages/grab-page-bundled-react-component.tsx b/src/functions/server/web-pages/grab-page-bundled-react-component.tsx index 023249a..cb8b6de 100644 --- a/src/functions/server/web-pages/grab-page-bundled-react-component.tsx +++ b/src/functions/server/web-pages/grab-page-bundled-react-component.tsx @@ -20,9 +20,12 @@ export default async function grabPageBundledReactComponent({ }: Params): Promise { try { if (global.SSR_BUNDLER_CTX_MAP?.[file_path]) { - const mod = await import( - path.join(ROOT_DIR, global.SSR_BUNDLER_CTX_MAP[file_path].path) + const abs = path.join( + ROOT_DIR, + global.SSR_BUNDLER_CTX_MAP[file_path].path, ); + Loader.registry.delete(abs); + const mod = await import(`${abs}?t=${Date.now()}`); const Main = mod.default as FC; diff --git a/src/functions/server/web-pages/grab-page-combined-server-res.ts b/src/functions/server/web-pages/grab-page-combined-server-res.ts index affd9c2..2ff1f74 100644 --- a/src/functions/server/web-pages/grab-page-combined-server-res.ts +++ b/src/functions/server/web-pages/grab-page-combined-server-res.ts @@ -40,6 +40,9 @@ export default async function grabPageCombinedServerRes({ ? path.join(ROOT_DIR, root_server_ctx_map.path) : root_server_file_path; + if (final_root_server_path) { + Loader.registry.delete(final_root_server_path); + } const root_server_module: BunextPageServerModule = final_root_server_path ? await import(`${final_root_server_path}?t=${now}`) : undefined; @@ -65,6 +68,9 @@ export default async function grabPageCombinedServerRes({ ? path.join(ROOT_DIR, page_server_ctx.path) : server_file_path; + if (final_page_server_path) { + Loader.registry.delete(final_page_server_path); + } const server_module: BunextPageServerModule = final_page_server_path ? await import(`${final_page_server_path}?t=${now}`) : undefined;