From 936add747624fb6b113d1c4a53301b25feb6ecae Mon Sep 17 00:00:00 2001 From: CharlieHelps Date: Thu, 30 Oct 2025 14:45:46 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20ignore=20webpack=20`publicPath:=20'a?= =?UTF-8?q?uto'`=20when=20generating=20manifest=20paths\n\nTreat=20'auto'?= =?UTF-8?q?=20as=20runtime-resolved=20publicPath=20so=20we=20don=E2=80=99t?= =?UTF-8?q?=20serialize=20it=20into=20the=20manifest.=20Adds=20a=20unit=20?= =?UTF-8?q?test=20covering=20the=20behavior.\n\nRefs=20#307?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks.ts | 8 +++++++- test/unit/paths.ts | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/hooks.ts b/src/hooks.ts index e45302e..3dee3b1 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -80,7 +80,13 @@ const emitHook = function emit( publicPath: true }); - const publicPath = options.publicPath !== null ? options.publicPath : stats.publicPath; + // Webpack v5 supports `output.publicPath: 'auto'`, which resolves the publicPath + // at runtime based on the current script/asset location. In that mode, the + // string value 'auto' should not be serialized into the manifest. Treat it as + // an "unset" publicPath so manifest values remain unprefixed and consumers can + // resolve at runtime. See https://webpack.js.org/guides/public-path/#automatic-publicpath + const resolvedPublicPath = options.publicPath !== null ? options.publicPath : stats.publicPath; + const publicPath = resolvedPublicPath === 'auto' ? '' : resolvedPublicPath; const { basePath, removeKeyHash } = options; emitCountMap.set(manifestFileName, emitCount); diff --git a/test/unit/paths.ts b/test/unit/paths.ts index dd6b6c0..db013b1 100644 --- a/test/unit/paths.ts +++ b/test/unit/paths.ts @@ -72,6 +72,26 @@ test('prefixes paths with a public path', async (t) => { }); }); +test("does not prefix paths when webpack's publicPath is 'auto'", async (t) => { + const config = { + context: __dirname, + entry: { + one: '../fixtures/file.js' + }, + output: { + filename: `[name].${hashLiteral}.js`, + path: join(outputPath, 'public-auto'), + // Webpack will resolve the publicPath at runtime; the manifest should not contain 'auto'. + publicPath: 'auto' + } + } as any; + const { manifest, stats } = await compile(config, t); + + t.deepEqual(manifest, { + 'one.js': `one.${(stats as any).hash}.js` + }); +}); + test(`prefixes paths with a public path and handle ${hashLiteral} from public path`, async (t) => { const config = { context: __dirname, From b0285b75fb16edf57a8523d056d9a5c07cf3ad05 Mon Sep 17 00:00:00 2001 From: CharlieHelps Date: Thu, 30 Oct 2025 15:07:53 +0000 Subject: [PATCH 2/2] test: port two 'publicPath: auto' cases from #308 (credit @chouchouji)\n\n- publicPath 'auto' + basePath still prefixes manifest keys\n- publicPath 'auto' + plugin publicPath override applies to values\n\nRefs #307 --- test/unit/paths.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/unit/paths.ts b/test/unit/paths.ts index db013b1..9baa9f1 100644 --- a/test/unit/paths.ts +++ b/test/unit/paths.ts @@ -92,6 +92,50 @@ test("does not prefix paths when webpack's publicPath is 'auto'", async (t) => { }); }); +test("prefixes definitions with a base path when webpack's publicPath is 'auto'", async (t) => { + const config = { + context: __dirname, + entry: { + one: '../fixtures/file.js' + }, + output: { + filename: `[name].${hashLiteral}.js`, + path: join(outputPath, 'public-auto-with-basePath'), + publicPath: 'auto' + } + } as any; + + const { manifest, stats } = await compile(config, t, { + basePath: '/app/' + }); + + t.deepEqual(manifest, { + '/app/one.js': `one.${(stats as any).hash}.js` + }); +}); + +test("uses plugin 'publicPath' override when webpack's publicPath is 'auto'", async (t) => { + const config = { + context: __dirname, + entry: { + one: '../fixtures/file.js' + }, + output: { + filename: `[name].${hashLiteral}.js`, + path: join(outputPath, 'public-auto-with-override'), + publicPath: 'auto' + } + } as any; + + const { manifest, stats } = await compile(config, t, { + publicPath: '/cdn/' + }); + + t.deepEqual(manifest, { + 'one.js': `/cdn/one.${(stats as any).hash}.js` + }); +}); + test(`prefixes paths with a public path and handle ${hashLiteral} from public path`, async (t) => { const config = { context: __dirname,