diff --git a/next.config.mjs b/next.config.mjs index 5a6d13722e..2f06962ee2 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -113,6 +113,17 @@ const nextConfig = { // PR-2 of diegosouzapw/OmniRoute#3932: tree-shake barrel re-exports so // route bundles don't pull in 14 locale files, every lucide-react icon, // or the full date-fns surface when only one helper is used. + // + // NOTE: this list must only contain EXTERNAL barrel libraries. Do NOT add + // the internal `@omniroute/open-sse` workspace here: optimizePackageImports + // makes Next.js resolve every export of the package's barrel at build time, + // and open-sse's `index.ts` re-exports the entire streaming engine + // (executors/translators/services/handlers/mcp-server — thousands of + // modules). Combined with the #3501 god-file splits (which multiplied the + // re-export edges), this drove the webpack production pass into a heap + // runaway that OOM'd even at a 28 GB --max-old-space-size (RSS pinned at the + // ceiling in a GC death-spiral). Removing it keeps the build's heap bounded. + // optimizePackageImports is designed for external libs, not workspaces. optimizePackageImports: [ "lobehub/icons", "@lobehub/icons", @@ -122,7 +133,6 @@ const nextConfig = { "lodash-es", "material-symbols", "next-intl", - "@omniroute/open-sse", ], }, outputFileTracingRoot: projectRoot, diff --git a/tests/unit/next-config.test.ts b/tests/unit/next-config.test.ts index 475735d936..4a523e50b2 100644 --- a/tests/unit/next-config.test.ts +++ b/tests/unit/next-config.test.ts @@ -232,3 +232,22 @@ test("next-intl webpack hook preserves caller config and filters known extractor false ); }); + +test("optimizePackageImports excludes the internal @omniroute/open-sse workspace (build-OOM guard)", async () => { + // Regression guard: adding the internal `@omniroute/open-sse` workspace to + // optimizePackageImports makes Next.js resolve its entire barrel at build + // time, driving the webpack production pass into a heap runaway that OOM'd + // even at 28 GB. optimizePackageImports is for EXTERNAL barrel libs only. + const { default: nextConfig } = await loadNextConfig("optimize-pkg-imports"); + const list = nextConfig.experimental?.optimizePackageImports ?? []; + + assert.ok(Array.isArray(list), "optimizePackageImports should be an array"); + assert.ok( + !list.includes("@omniroute/open-sse"), + "do NOT add the internal @omniroute/open-sse workspace to optimizePackageImports — it OOMs the production build" + ); + // The intended external barrel libs must remain optimized. + for (const lib of ["lucide-react", "date-fns", "next-intl"]) { + assert.ok(list.includes(lib), `expected external barrel lib ${lib} to stay optimized`); + } +});