Ordering and conflicting order warning
This commit is contained in:
parent
16784692d3
commit
277a8bb19e
|
@ -15,9 +15,7 @@ const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifier
|
|||
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
|
||||
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
||||
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
||||
const {
|
||||
compareModulesByPostOrderIndexOrIdentifier
|
||||
} = require("../util/comparators");
|
||||
const { compareModulesByIdentifier } = require("../util/comparators");
|
||||
const createSchemaValidation = require("../util/create-schema-validation");
|
||||
const createHash = require("../util/createHash");
|
||||
const memoize = require("../util/memoize");
|
||||
|
@ -192,7 +190,8 @@ class CssModulesPlugin {
|
|||
chunk,
|
||||
chunkGraph,
|
||||
codeGenerationResults,
|
||||
uniqueName: compilation.outputOptions.uniqueName
|
||||
uniqueName: compilation.outputOptions.uniqueName,
|
||||
compilation
|
||||
}),
|
||||
filenameTemplate: CssModulesPlugin.getChunkFilenameTemplate(
|
||||
chunk,
|
||||
|
@ -236,24 +235,140 @@ class CssModulesPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
getOrderedChunkCssModules(chunk, chunkGraph) {
|
||||
const cssImports = chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css-import",
|
||||
// TODO improve order function
|
||||
compareModulesByPostOrderIndexOrIdentifier(chunkGraph.moduleGraph)
|
||||
);
|
||||
const cssContent = chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css",
|
||||
// TODO improve order function
|
||||
compareModulesByPostOrderIndexOrIdentifier(chunkGraph.moduleGraph)
|
||||
);
|
||||
return [...(cssImports || []), ...(cssContent || [])];
|
||||
getModulesInOrder(chunk, modules, compilation) {
|
||||
if (!modules) return [];
|
||||
|
||||
const modulesList = [...modules];
|
||||
|
||||
// Get ordered list of modules per chunk group
|
||||
// Lists are in reverse order to allow to use Array.pop()
|
||||
const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
|
||||
const sortedModules = modulesList
|
||||
.map(module => {
|
||||
return {
|
||||
module,
|
||||
index: chunkGroup.getModulePostOrderIndex(module)
|
||||
};
|
||||
})
|
||||
.filter(item => item.index !== undefined)
|
||||
.sort((a, b) => b.index - a.index)
|
||||
.map(item => item.module);
|
||||
|
||||
return { list: sortedModules, set: new Set(sortedModules) };
|
||||
});
|
||||
|
||||
if (modulesByChunkGroup.length === 1)
|
||||
return modulesByChunkGroup[0].list.reverse();
|
||||
|
||||
const compareModuleLists = ({ list: a }, { list: b }) => {
|
||||
if (a.length === 0) {
|
||||
return b.length === 0 ? 0 : 1;
|
||||
} else {
|
||||
if (b.length === 0) return -1;
|
||||
return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
modulesByChunkGroup.sort(compareModuleLists);
|
||||
|
||||
const finalModules = [];
|
||||
|
||||
for (;;) {
|
||||
const failedModules = new Set();
|
||||
const list = modulesByChunkGroup[0].list;
|
||||
if (list.length === 0) {
|
||||
// done, everything empty
|
||||
break;
|
||||
}
|
||||
let selectedModule = list[list.length - 1];
|
||||
let hasFailed = undefined;
|
||||
outer: for (;;) {
|
||||
for (const { list, set } of modulesByChunkGroup) {
|
||||
if (list.length === 0) continue;
|
||||
const lastModule = list[list.length - 1];
|
||||
if (lastModule === selectedModule) continue;
|
||||
if (!set.has(selectedModule)) continue;
|
||||
failedModules.add(selectedModule);
|
||||
if (failedModules.has(lastModule)) {
|
||||
// There is a conflict, try other alternatives
|
||||
hasFailed = lastModule;
|
||||
continue;
|
||||
}
|
||||
selectedModule = lastModule;
|
||||
hasFailed = false;
|
||||
continue outer; // restart
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (hasFailed) {
|
||||
// There is a not resolve-able conflict with the selectedModule
|
||||
if (compilation) {
|
||||
// TODO print better warning
|
||||
compilation.warnings.push(
|
||||
new Error(
|
||||
`chunk ${
|
||||
chunk.name || chunk.id
|
||||
}\nConflicting order between ${hasFailed.readableIdentifier(
|
||||
compilation.requestShortener
|
||||
)} and ${selectedModule.readableIdentifier(
|
||||
compilation.requestShortener
|
||||
)}`
|
||||
)
|
||||
);
|
||||
}
|
||||
selectedModule = hasFailed;
|
||||
}
|
||||
// Insert the selected module into the final modules list
|
||||
finalModules.push(selectedModule);
|
||||
// Remove the selected module from all lists
|
||||
for (const { list, set } of modulesByChunkGroup) {
|
||||
const lastModule = list[list.length - 1];
|
||||
if (lastModule === selectedModule) list.pop();
|
||||
else if (hasFailed && set.has(selectedModule)) {
|
||||
const idx = list.indexOf(selectedModule);
|
||||
if (idx >= 0) list.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
modulesByChunkGroup.sort(compareModuleLists);
|
||||
}
|
||||
return finalModules;
|
||||
}
|
||||
|
||||
renderChunk({ uniqueName, chunk, chunkGraph, codeGenerationResults }) {
|
||||
const modules = this.getOrderedChunkCssModules(chunk, chunkGraph);
|
||||
getOrderedChunkCssModules(chunk, chunkGraph, compilation) {
|
||||
return [
|
||||
...this.getModulesInOrder(
|
||||
chunk,
|
||||
chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css-import",
|
||||
compareModulesByIdentifier
|
||||
),
|
||||
compilation
|
||||
),
|
||||
...this.getModulesInOrder(
|
||||
chunk,
|
||||
chunkGraph.getOrderedChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"css",
|
||||
compareModulesByIdentifier
|
||||
),
|
||||
compilation
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
renderChunk({
|
||||
uniqueName,
|
||||
chunk,
|
||||
chunkGraph,
|
||||
codeGenerationResults,
|
||||
compilation
|
||||
}) {
|
||||
const modules = this.getOrderedChunkCssModules(
|
||||
chunk,
|
||||
chunkGraph,
|
||||
compilation
|
||||
);
|
||||
const source = new ConcatSource();
|
||||
const metaData = [];
|
||||
for (const module of modules) {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: a;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: b;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: c;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: d;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
color: e;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
it("should lead to conflicting order warning", done => {
|
||||
__non_webpack_require__("./lazy4_js.bundle0.js");
|
||||
Promise.all([
|
||||
import("./lazy1.css"),
|
||||
import("./lazy2.css"),
|
||||
import("./lazy3.css"),
|
||||
import("./lazy4.js")
|
||||
]).then(() => {
|
||||
try {
|
||||
const matches = fs
|
||||
.readFileSync(path.join(__dirname, "css.bundle0.css"), "utf-8")
|
||||
.match(/color: ([a-z0-9])/g)
|
||||
.map(match => match[7]);
|
||||
expect(matches).toEqual("bcdea123".split(""));
|
||||
done();
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
}, done);
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
@import "b.css";
|
||||
@import "c.css";
|
||||
@import "a.css";
|
||||
|
||||
body {
|
||||
color: 1;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
@import "c.css";
|
||||
@import "b.css";
|
||||
@import "a.css";
|
||||
|
||||
body {
|
||||
color: 2;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
@import "d.css";
|
||||
@import "a.css";
|
||||
|
||||
body {
|
||||
color: 3;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
import "./e.css";
|
||||
import "./a.css";
|
|
@ -0,0 +1 @@
|
|||
module.exports = [[/Conflicting order between \.\/b\.css and \.\/c\.css/]];
|
|
@ -0,0 +1,25 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
experiments: {
|
||||
css: true
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
css: {
|
||||
type: "css",
|
||||
enforce: true,
|
||||
name: "css"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
externalsPresets: {
|
||||
node: true
|
||||
},
|
||||
node: {
|
||||
__dirname: false
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue