diff --git a/scripts/dev/webpack-config-light.test.cjs b/scripts/dev/webpack-config-light.test.cjs index 38301c192..740c0129a 100644 --- a/scripts/dev/webpack-config-light.test.cjs +++ b/scripts/dev/webpack-config-light.test.cjs @@ -49,6 +49,53 @@ test("light dev disables webpack dev-server browser client", () => { assert.equal(htmlPlugin?.userOptions?.retryMainScriptLoad, false); }); +test("light development cache stays memory-only and bounded", () => { + const config = withEnv( + { + ORGII_LIGHT_DEV: "true", + FAST_DEV: "true", + DEV_SOURCEMAPS: "false", + }, + () => createWebpackConfig({}, { mode: "development" }) + ); + + assert.deepEqual(config.cache, { + type: "memory", + maxGenerations: 1, + }); +}); + +test("standard development keeps its filesystem cache", () => { + const config = withEnv( + { + ORGII_LIGHT_DEV: null, + FAST_DEV: null, + DEV_SOURCEMAPS: null, + }, + () => createWebpackConfig({}, { mode: "development" }) + ); + + assert.equal(config.cache.type, "filesystem"); + assert.equal(config.cache.version, "dev-11"); +}); + +test("production keeps its isolated filesystem cache", () => { + for (const fastProd of [false, true]) { + const config = withEnv( + { + FAST_PROD: fastProd ? "true" : null, + }, + () => createWebpackConfig({}, { mode: "production" }) + ); + + assert.equal(config.cache.type, "filesystem"); + assert.equal( + config.cache.version, + `${fastProd ? "prod-fast" : "prod"}-11` + ); + } +}); + test("retrying main script loader disables static HTML injection in dev", () => { const config = withEnv( { diff --git a/webpack.config.js b/webpack.config.js index 0ad0e91df..1cd44d3fb 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -62,24 +62,33 @@ module.exports = (env, argv) => { chunkFilename: isProduction ? "[name].[contenthash].js" : "[name].js", clean: true, }, - cache: { - type: "filesystem", - // FAST_PROD swaps both the transpiler and minimizer. Keep it in a - // separate filesystem-cache namespace so webpack cannot reuse cached - // runtime-condition code generated by the regular production pipeline. - // Mixing those caches can leave async chunks guarded by a stale runtime - // id (for example `__webpack_require__.j == 9121` while the emitted - // runtime id is `49121`), which turns otherwise valid imports into - // `undefined` only in the packaged app. - version: `${ - isProduction ? (useFastProd ? "prod-fast" : "prod") : "dev" - }-11`, - buildDependencies: { - config: [__filename], - }, - // Don't compress - avoids sass serialization issues - compression: false, - }, + cache: isLightDev + ? { + // Webpack's filesystem cache can serialize gigabyte-scale pack files + // for this app and raises the light-dev rebuild RSS ceiling. Retain + // only one unused generation and never persist the light-mode + // compilation graph across restarts. + type: "memory", + maxGenerations: 1, + } + : { + type: "filesystem", + // FAST_PROD swaps both the transpiler and minimizer. Keep it in a + // separate filesystem-cache namespace so webpack cannot reuse cached + // runtime-condition code generated by the regular production pipeline. + // Mixing those caches can leave async chunks guarded by a stale runtime + // id (for example `__webpack_require__.j == 9121` while the emitted + // runtime id is `49121`), which turns otherwise valid imports into + // `undefined` only in the packaged app. + version: isProduction + ? `${useFastProd ? "prod-fast" : "prod"}-11` + : "dev-11", + buildDependencies: { + config: [__filename], + }, + // Don't compress - avoids sass serialization issues + compression: false, + }, // Snapshot: use timestamps for node_modules instead of content hashing. // node_modules rarely change during a dev session; timestamp checks are much faster. snapshot: {