Bugfix: update stale HMR after fixed errors

This commit is contained in:
Benjamin Toby 2026-07-20 20:54:39 +01:00
parent e3a0f5fbeb
commit a9cd51d71c
14 changed files with 71 additions and 63 deletions

View File

@ -56,20 +56,13 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn,
_.merge(global.BUNDLER_CTX_MAP[artifact.local_path], artifact); _.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); const elapsed = (performance.now() - build_start).toFixed(0);
log.success(`[Built] in ${elapsed}ms`); log.success(`[Built] in ${elapsed}ms`);
global.RECOMPILING = false;
global.IS_SERVER_COMPONENT = false;
global.MAIN_CTX_BUILD_STARTS = 0; global.MAIN_CTX_BUILD_STARTS = 0;
global.BUNDLER_CTX_DISPOSED = false; global.BUNDLER_CTX_DISPOSED = false;
const does_error_file_exist = existsSync(BUNX_BUNDLER_ERROR_EXIT_FILE); const does_error_file_exist = existsSync(BUNX_BUNDLER_ERROR_EXIT_FILE);
// SSR must finish before HMR so server props are fresh
if (build_only) { if (build_only) {
try { try {
await pagesSSRBundler(); await pagesSSRBundler();
@ -92,12 +85,17 @@ export default function esbuildCTXArtifactTracker({ entryToPage, post_build_fn,
catch (error) { catch (error) {
log.error(`SSR Bundler Error: ${error}`); log.error(`SSR Bundler Error: ${error}`);
} }
if (artifacts?.[0] && artifacts.length > 0) {
try {
await post_build_fn?.({ artifacts });
} }
// if (global.SSR_BUNDLER_CTX) { catch (error) {
// global.SSR_BUNDLER_CTX.rebuild(); log.error(`Post-build Error: ${error}`);
// } else { }
// pagesSSRContextBundler(); }
// } }
global.RECOMPILING = false;
global.IS_SERVER_COMPONENT = false;
}); });
}, },
}; };

View File

@ -40,8 +40,8 @@ export default async function bunextInit(params) {
else if (is_dev) { else if (is_dev) {
log.build(`Building Modules ...`); log.build(`Building Modules ...`);
await allPagesESBuildContextBundler({ await allPagesESBuildContextBundler({
post_build_fn: () => { post_build_fn: async () => {
serverPostBuildFn(); await serverPostBuildFn();
}, },
}); });
watcherEsbuildCTX(); watcherEsbuildCTX();

View File

@ -18,8 +18,8 @@ export default async function fullRebuild(params) {
} }
catch (error) { } catch (error) { }
await allPagesESBuildContextBundler({ await allPagesESBuildContextBundler({
post_build_fn: () => { post_build_fn: async () => {
serverPostBuildFn(); await serverPostBuildFn();
}, },
}); });
} }

View File

@ -43,17 +43,16 @@ export default async function serverPostBuildFn(params) {
const mock_req = target_artifact.req_url const mock_req = target_artifact.req_url
? new Request(target_artifact.req_url) ? new Request(target_artifact.req_url)
: new Request(controller.page_url); : new Request(controller.page_url);
const page_component = global.IS_SERVER_COMPONENT // Always re-run server fns so fixed errors clear on the first HMR
? await grabPageComponent({ const page_component = await grabPageComponent({
req: mock_req, req: mock_req,
return_server_res_only: true, return_server_res_only: true,
is_hydration: true, is_hydration: true,
}) });
: {};
if (page_component instanceof Response) { if (page_component instanceof Response) {
continue; continue;
} }
const { serverRes } = page_component; const { serverRes } = page_component || {};
const final_artifact = { const final_artifact = {
..._.omit(controller, ["controller"]), ..._.omit(controller, ["controller"]),
target_map: target_artifact, target_map: target_artifact,
@ -61,9 +60,8 @@ export default async function serverPostBuildFn(params) {
if (!target_artifact) { if (!target_artifact) {
delete final_artifact.target_map; delete final_artifact.target_map;
} }
if (serverRes) { // Always replace so prior error props cannot linger
final_artifact.page_props = serverRes; final_artifact.page_props = serverRes || {};
}
try { try {
let final_data = {}; let final_data = {};
if (global.ROOT_FILE_UPDATED) { if (global.ROOT_FILE_UPDATED) {

View File

@ -8,7 +8,9 @@ const { ROOT_DIR } = grabDirNames();
export default async function grabPageBundledReactComponent({ file_path, return_tsx_only, }) { export default async function grabPageBundledReactComponent({ file_path, return_tsx_only, }) {
try { try {
if (global.SSR_BUNDLER_CTX_MAP?.[file_path]) { 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; const Main = mod.default;
return { component: Main }; return { component: Main };
} }

View File

@ -16,6 +16,9 @@ export default async function grabPageCombinedServerRes({ file_path, debug, url,
const final_root_server_path = root_server_ctx_map?.local_path const final_root_server_path = root_server_ctx_map?.local_path
? path.join(ROOT_DIR, root_server_ctx_map.path) ? path.join(ROOT_DIR, root_server_ctx_map.path)
: root_server_file_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 const root_server_module = final_root_server_path
? await import(`${final_root_server_path}?t=${now}`) ? await import(`${final_root_server_path}?t=${now}`)
: undefined; : undefined;
@ -34,6 +37,9 @@ export default async function grabPageCombinedServerRes({ file_path, debug, url,
const final_page_server_path = page_server_ctx?.local_path const final_page_server_path = page_server_ctx?.local_path
? path.join(ROOT_DIR, page_server_ctx.path) ? path.join(ROOT_DIR, page_server_ctx.path)
: server_file_path; : server_file_path;
if (final_page_server_path) {
Loader.registry.delete(final_page_server_path);
}
const server_module = final_page_server_path const server_module = final_page_server_path
? await import(`${final_page_server_path}?t=${now}`) ? await import(`${final_page_server_path}?t=${now}`)
: undefined; : undefined;

View File

@ -1,6 +1,6 @@
{ {
"name": "@moduletrace/bunext", "name": "@moduletrace/bunext",
"version": "1.0.96", "version": "1.0.97",
"main": "dist/index.js", "main": "dist/index.js",
"module": "index.ts", "module": "index.ts",
"dependencies": { "dependencies": {

View File

@ -8,8 +8,8 @@ export default async function buildOnstartErrorHandler(params?: Params) {
return; return;
} }
console.log(`Killing Bundler ...`); // console.log(`Killing Bundler ...`);
console.log(`global.BUNDLER_CTX_DISPOSED`, global.BUNDLER_CTX_DISPOSED); // console.log(`global.BUNDLER_CTX_DISPOSED`, global.BUNDLER_CTX_DISPOSED);
global.BUNDLER_CTX_DISPOSED = true; global.BUNDLER_CTX_DISPOSED = true;

View File

@ -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); const elapsed = (performance.now() - build_start).toFixed(0);
log.success(`[Built] in ${elapsed}ms`); log.success(`[Built] in ${elapsed}ms`);
global.RECOMPILING = false;
global.IS_SERVER_COMPONENT = false;
global.MAIN_CTX_BUILD_STARTS = 0; global.MAIN_CTX_BUILD_STARTS = 0;
global.BUNDLER_CTX_DISPOSED = false; global.BUNDLER_CTX_DISPOSED = false;
@ -118,6 +109,7 @@ export default function esbuildCTXArtifactTracker({
BUNX_BUNDLER_ERROR_EXIT_FILE, BUNX_BUNDLER_ERROR_EXIT_FILE,
); );
// SSR must finish before HMR so server props are fresh
if (build_only) { if (build_only) {
try { try {
await pagesSSRBundler(); await pagesSSRBundler();
@ -139,13 +131,18 @@ export default function esbuildCTXArtifactTracker({
} catch (error) { } catch (error) {
log.error(`SSR Bundler Error: ${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.RECOMPILING = false;
// global.SSR_BUNDLER_CTX.rebuild(); global.IS_SERVER_COMPONENT = false;
// } else {
// pagesSSRContextBundler();
// }
}); });
}, },
}; };

View File

@ -98,8 +98,8 @@ export default async function bunextInit(params?: Params) {
} else if (is_dev) { } else if (is_dev) {
log.build(`Building Modules ...`); log.build(`Building Modules ...`);
await allPagesESBuildContextBundler({ await allPagesESBuildContextBundler({
post_build_fn: () => { post_build_fn: async () => {
serverPostBuildFn(); await serverPostBuildFn();
}, },
}); });
watcherEsbuildCTX(); watcherEsbuildCTX();

View File

@ -24,8 +24,8 @@ export default async function fullRebuild(params?: { msg?: string }) {
} catch (error) {} } catch (error) {}
await allPagesESBuildContextBundler({ await allPagesESBuildContextBundler({
post_build_fn: () => { post_build_fn: async () => {
serverPostBuildFn(); await serverPostBuildFn();
}, },
}); });
} catch (error: any) { } catch (error: any) {

View File

@ -57,19 +57,18 @@ export default async function serverPostBuildFn(params?: Params) {
? new Request(target_artifact.req_url) ? new Request(target_artifact.req_url)
: new Request(controller.page_url); : new Request(controller.page_url);
const page_component = global.IS_SERVER_COMPONENT // Always re-run server fns so fixed errors clear on the first HMR
? await grabPageComponent({ const page_component = await grabPageComponent({
req: mock_req, req: mock_req,
return_server_res_only: true, return_server_res_only: true,
is_hydration: true, is_hydration: true,
}) });
: {};
if (page_component instanceof Response) { if (page_component instanceof Response) {
continue; continue;
} }
const { serverRes } = page_component; const { serverRes } = page_component || {};
const final_artifact: Omit<GlobalHMRControllerObject, "controller"> = { const final_artifact: Omit<GlobalHMRControllerObject, "controller"> = {
..._.omit(controller, ["controller"]), ..._.omit(controller, ["controller"]),
@ -80,9 +79,8 @@ export default async function serverPostBuildFn(params?: Params) {
delete final_artifact.target_map; delete final_artifact.target_map;
} }
if (serverRes) { // Always replace so prior error props cannot linger
final_artifact.page_props = serverRes; final_artifact.page_props = serverRes || {};
}
try { try {
let final_data: { [k: string]: any } = {}; let final_data: { [k: string]: any } = {};

View File

@ -20,9 +20,12 @@ export default async function grabPageBundledReactComponent({
}: Params): Promise<GrabPageReactBundledComponentRes | undefined> { }: Params): Promise<GrabPageReactBundledComponentRes | undefined> {
try { try {
if (global.SSR_BUNDLER_CTX_MAP?.[file_path]) { if (global.SSR_BUNDLER_CTX_MAP?.[file_path]) {
const mod = await import( const abs = path.join(
path.join(ROOT_DIR, global.SSR_BUNDLER_CTX_MAP[file_path].path) 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; const Main = mod.default as FC;

View File

@ -40,6 +40,9 @@ export default async function grabPageCombinedServerRes({
? path.join(ROOT_DIR, root_server_ctx_map.path) ? path.join(ROOT_DIR, root_server_ctx_map.path)
: root_server_file_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 const root_server_module: BunextPageServerModule = final_root_server_path
? await import(`${final_root_server_path}?t=${now}`) ? await import(`${final_root_server_path}?t=${now}`)
: undefined; : undefined;
@ -65,6 +68,9 @@ export default async function grabPageCombinedServerRes({
? path.join(ROOT_DIR, page_server_ctx.path) ? path.join(ROOT_DIR, page_server_ctx.path)
: server_file_path; : server_file_path;
if (final_page_server_path) {
Loader.registry.delete(final_page_server_path);
}
const server_module: BunextPageServerModule = final_page_server_path const server_module: BunextPageServerModule = final_page_server_path
? await import(`${final_page_server_path}?t=${now}`) ? await import(`${final_page_server_path}?t=${now}`)
: undefined; : undefined;