Fix memory leak in dev server

This commit is contained in:
2026-10-16 14:25:18 +01:00
parent 3d0771f2d0
commit 5dc783fe97
36 changed files with 642 additions and 406 deletions
@@ -180,8 +180,27 @@ export default async function genWebHTML({
let render_error: any;
let has_render_error = false;
const render_timeout_ms =
global.BUNEXT_CONFIG.ssr_render_timeout_ms ||
AppData["DefaultSSRRenderTimeoutMs"];
// Without a deadline, a Suspense boundary that never settles keeps the
// request (and its whole render tree) alive forever. The timer is
// cleared once the render ends so finished requests don't linger.
const render_abort = new AbortController();
const render_timeout = setTimeout(
() =>
render_abort.abort(
new RenderTimeoutError(
`Page render timed out after ${render_timeout_ms}ms`,
),
),
render_timeout_ms,
);
try {
const stream = await renderToReadableStream(final_component, {
signal: render_abort.signal,
onError(error: any) {
if (error?.message?.includes('unique "key" prop')) return;
@@ -190,12 +209,16 @@ export default async function genWebHTML({
render_error = error;
}
original_console.error(error);
// A timeout has no useful stack; it's logged upstream.
if (!(error instanceof RenderTimeoutError)) {
original_console.error(error);
}
},
});
htmlBody = await new Response(stream).text();
} finally {
clearTimeout(render_timeout);
restoreConsole();
}
@@ -211,6 +234,8 @@ export default async function genWebHTML({
return html;
}
class RenderTimeoutError extends Error {}
let original_console: Pick<
Console,
"log" | "warn" | "error" | "info" | "debug"
@@ -1,45 +0,0 @@
import isDevelopment from "../../../utils/is-development";
import * as esbuild from "esbuild";
import grabDirNames from "../../../utils/grab-dir-names";
import path from "path";
import tailwindEsbuildPlugin from "./tailwind-esbuild-plugin";
type Params = {
file_path: string;
out_file?: string;
};
export default async function grabFilePathModule<T extends any = any>({
file_path,
out_file,
}: Params): Promise<T> {
const dev = isDevelopment();
const { BUNX_CWD_MODULE_CACHE_DIR } = grabDirNames();
const target_cache_file_path =
out_file ||
path.join(BUNX_CWD_MODULE_CACHE_DIR, `${path.basename(file_path)}.js`);
await esbuild.build({
entryPoints: [file_path],
bundle: true,
format: "esm",
target: "es2020",
platform: "node",
// external: ["react", "react-dom"],
minify: true,
define: {
"process.env.NODE_ENV": JSON.stringify(
dev ? "development" : "production",
),
},
metafile: true,
plugins: [tailwindEsbuildPlugin],
jsx: "automatic",
outfile: target_cache_file_path,
});
// Loader.registry.delete(target_cache_file_path);
const module = await import(`${target_cache_file_path}?t=${Date.now()}`);
return module as T;
}