make multiple assets to the same filename a warning

check source content to when comparing assets for warning
This commit is contained in:
Tobias Koppers 2019-09-13 08:42:36 +02:00
parent c5450b460e
commit e41fab0bc3
10 changed files with 78 additions and 4 deletions

View File

@ -37,11 +37,11 @@ const compareLocations = require("./compareLocations");
const { Logger, LogType } = require("./logging/Logger");
const ErrorHelpers = require("./ErrorHelpers");
const buildChunkGraph = require("./buildChunkGraph");
const WebpackError = require("./WebpackError");
/** @typedef {import("./Module")} Module */
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./DependenciesBlockVariable")} DependenciesBlockVariable */
/** @typedef {import("./dependencies/SingleEntryDependency")} SingleEntryDependency */
/** @typedef {import("./dependencies/MultiEntryDependency")} MultiEntryDependency */
@ -221,6 +221,25 @@ const addAllToSet = (set, otherSet) => {
}
};
/**
* @param {Source} a a source
* @param {Source} b another source
* @returns {boolean} true, when both sources are equal
*/
const isSourceEqual = (a, b) => {
if (a === b) return true;
// TODO webpack 5: check .buffer() instead, it's called anyway during emit
/** @type {Buffer|string} */
let aSource = a.source();
/** @type {Buffer|string} */
let bSource = b.source();
if (aSource === bSource) return true;
if (typeof aSource === "string" && typeof bSource === "string") return false;
if (!Buffer.isBuffer(aSource)) aSource = Buffer.from(aSource, "utf-8");
if (!Buffer.isBuffer(bSource)) bSource = Buffer.from(bSource, "utf-8");
return aSource.equals(bSource);
};
class Compilation extends Tapable {
/**
* Creates an instance of Compilation.
@ -1990,10 +2009,16 @@ class Compilation extends Tapable {
*/
emitAsset(file, source, assetInfo = {}) {
if (this.assets[file]) {
if (this.assets[file] !== source) {
throw new Error(
`Conflict: Multiple assets emit to the same filename ${file}`
if (!isSourceEqual(this.assets[file], source)) {
// TODO webpack 5: make this an error instead
this.warnings.push(
new WebpackError(
`Conflict: Multiple assets emit different content to the same filename ${file}`
)
);
this.assets[file] = source;
this.assetsInfo.set(file, assetInfo);
return;
}
const oldInfo = this.assetsInfo.get(file);
this.assetsInfo.set(file, Object.assign({}, oldInfo, assetInfo));

View File

@ -0,0 +1,4 @@
it("should compile without warnings", () => {
require("./test1.txt");
require("./test2.txt");
});

View File

@ -0,0 +1 @@
Hello World

View File

@ -0,0 +1 @@
Something else

View File

@ -0,0 +1,7 @@
module.exports = [
[
/Conflict/,
/Multiple assets emit different content to the same filename/,
/same-name\.txt/
]
];

View File

@ -0,0 +1,15 @@
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: "file-loader",
options: {
name: "same-name.txt"
}
}
}
]
}
};

View File

@ -0,0 +1,4 @@
it("should compile without warnings", () => {
require("./test1.txt");
require("./test2.txt");
});

View File

@ -0,0 +1 @@
Hello World

View File

@ -0,0 +1 @@
Hello World

View File

@ -0,0 +1,15 @@
module.exports = {
module: {
rules: [
{
test: /\.txt$/,
use: {
loader: "file-loader",
options: {
name: "same-name.txt"
}
}
}
]
}
};