Skip to content

Commit b50063e

Browse files
fix: a generated file keeps nothing its name carried before
webpack merges an info object into the old one, so writing over an existing name kept its immutable and sourceFilename; a function replaces instead.
1 parent a6047ae commit b50063e

2 files changed

Lines changed: 64 additions & 3 deletions

File tree

‎src/index.js‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,10 +1746,14 @@ class MinimizerPlugin {
17461746
generatedInfo.immutable = true;
17471747
}
17481748

1749-
// A rebuild writes over the file it wrote last time rather than a new one,
1750-
// and what is recorded below is owed either way.
1749+
// Handed over as a function, which replaces: an object is merged into what
1750+
// the name carried before, and this file inherits nothing.
17511751
if (compilation.getAsset(generatedName)) {
1752-
compilation.updateAsset(generatedName, generatedSource, generatedInfo);
1752+
compilation.updateAsset(
1753+
generatedName,
1754+
generatedSource,
1755+
() => generatedInfo,
1756+
);
17531757
} else {
17541758
compilation.emitAsset(generatedName, generatedSource, generatedInfo);
17551759
}

‎test/generate-option.test.js‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,63 @@ describe("generate over a file that is already there", () => {
21752175
expect(readAsset("image.copy.png", compiler, stats)).not.toBe("stale");
21762176
});
21772177

2178+
it("should not keep what the name it wrote over promised", async () => {
2179+
const compiler = getCompiler({
2180+
entry: path.resolve(__dirname, "./fixtures/images.js"),
2181+
module: { rules: IMAGE_RULES },
2182+
});
2183+
2184+
/** Writes the name the generator is about to write, and promises for it. */
2185+
class AlreadyThere {
2186+
/**
2187+
* @param {import("webpack").Compiler} instance compiler
2188+
* @returns {void}
2189+
*/
2190+
apply(instance) {
2191+
instance.hooks.compilation.tap("AlreadyThere", (compilation) => {
2192+
compilation.hooks.processAssets.tap(
2193+
{
2194+
name: "AlreadyThere",
2195+
stage:
2196+
compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
2197+
},
2198+
() => {
2199+
compilation.emitAsset(
2200+
"image.copy.png",
2201+
new compiler.webpack.sources.RawSource(Buffer.from("stale")),
2202+
{ immutable: true, sourceFilename: "somewhere/else.png" },
2203+
);
2204+
},
2205+
);
2206+
});
2207+
}
2208+
}
2209+
2210+
new AlreadyThere().apply(compiler);
2211+
new MinimizerPlugin({
2212+
test: /^image\.png$/i,
2213+
generate: {
2214+
implementation: (input) => ({
2215+
code: Buffer.from(Object.values(input)[0]),
2216+
}),
2217+
type: "asset",
2218+
filename: "[path][name].copy[ext]",
2219+
},
2220+
}).apply(compiler);
2221+
2222+
const stats = await compile(compiler);
2223+
const { info } = /** @type {import("webpack").Asset} */ (
2224+
stats.compilation.getAsset("image.copy.png")
2225+
);
2226+
2227+
expect(getErrors(stats)).toEqual([]);
2228+
// What the generator says of the file it wrote, and nothing the name
2229+
// carried before it: webpack merges an info object into the old one.
2230+
expect(info.immutable).toBeUndefined();
2231+
expect(info.sourceFilename).toBeUndefined();
2232+
expect(info.generated).toBe(true);
2233+
});
2234+
21782235
it("should record `related` on the original where it is kept", async () => {
21792236
const compiler = getCompiler({
21802237
entry: path.resolve(__dirname, "./fixtures/images.js"),

0 commit comments

Comments
 (0)