fix: keep module traversal consistent across reexport scenarios (#19702)

This commit is contained in:
Natsu Xiao 2025-07-15 17:53:58 +08:00 committed by GitHub
parent fdb0c4efe3
commit 89eb6a3c81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 110 additions and 2 deletions

View File

@ -320,8 +320,17 @@ class SideEffectsFlagPlugin {
({ module }) =>
module.getSideEffectsConnectionState(moduleGraph) ===
false,
({ module: newModule, export: exportName }) => {
({
module: newModule,
export: exportName,
connection: targetConnection
}) => {
moduleGraph.updateModule(dep, newModule);
moduleGraph.updateParent(
dep,
targetConnection,
/** @type {Module} */ (connection.originModule)
);
moduleGraph.addExplanation(
dep,
"(skipped side-effect-free modules)"

View File

@ -556,7 +556,7 @@ const sortWithSourceOrder = (dependencies, dependencySourceOrderMap) => {
}
}
if (withSourceOrder.length === 0) {
if (withSourceOrder.length <= 1) {
return;
}

View File

@ -3498,6 +3498,8 @@ exports[`ConfigCacheTestCases css css-modules-no-space exported tests should all
exports[`ConfigCacheTestCases css css-order exported tests keep consistent css order 1`] = `".button-module { padding: 8px 16px; background-color: #007bff; color: white; border: none; border-radius: 4px;}.teaser-module { padding: 20px; border: 1px solid #ddd; border-radius: 8px; margin: 16px;}.teaser-module { background-color: orange;}"`;
exports[`ConfigCacheTestCases css css-order-reexport exported tests keep consistent css order 1`] = `".dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;
exports[`ConfigCacheTestCases css css-order2 exported tests keep consistent css order 1`] = `".dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;
exports[`ConfigCacheTestCases css css-order3 exported tests keep consistent css order 1`] = `".dependency3::before { content: \\"dependency3\\";}.dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;

View File

@ -3498,6 +3498,8 @@ exports[`ConfigTestCases css css-modules-no-space exported tests should allow to
exports[`ConfigTestCases css css-order exported tests keep consistent css order 1`] = `".button-module { padding: 8px 16px; background-color: #007bff; color: white; border: none; border-radius: 4px;}.teaser-module { padding: 20px; border: 1px solid #ddd; border-radius: 8px; margin: 16px;}.teaser-module { background-color: orange;}"`;
exports[`ConfigTestCases css css-order-reexport exported tests keep consistent css order 1`] = `".dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;
exports[`ConfigTestCases css css-order2 exported tests keep consistent css order 1`] = `".dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;
exports[`ConfigTestCases css css-order3 exported tests keep consistent css order 1`] = `".dependency3::before { content: \\"dependency3\\";}.dependency2::before { content: \\"dependency2\\";}.dependency::before { content: \\"dependency\\";}"`;

View File

@ -0,0 +1,5 @@
export { dependency, dependency2 } from "./dependency";
export function component(...args) {
console.log(args);
}

View File

@ -0,0 +1,3 @@
.dependency::before {
content: "dependency";
}

View File

@ -0,0 +1,5 @@
import styles from "./dependency.css";
export function dependency() {
return styles !== undefined;
}

View File

@ -0,0 +1,3 @@
.dependency2::before {
content: "dependency2";
}

View File

@ -0,0 +1,5 @@
import styles from "./dependency2.css";
export function dependency2() {
return styles !== undefined;
}

View File

@ -0,0 +1,2 @@
export * from "./dependency2";
export * from "./dependency";

View File

@ -0,0 +1,7 @@
{
"name": "dependency",
"version": "1.0.0",
"private": true,
"sideEffects": false,
"main": "index.js"
}

View File

@ -0,0 +1,14 @@
import { component, dependency, dependency2 } from "./component";
component(dependency, dependency2);
// https://github.com/webpack/webpack/issues/18961
// https://github.com/jantimon/reproduction-webpack-css-order
it("keep consistent css order", function() {
const fs = __non_webpack_require__("fs");
let source = fs.readFileSync(__dirname + "/main.css", "utf-8");
expect(removeComments(source)).toMatchSnapshot()
});
function removeComments(source) {
return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\n/g, "");
}

View File

@ -0,0 +1,8 @@
{
"name": "css-order2",
"version": "1.0.0",
"sideEffects": false,
"devDependencies": {
"mini-css-extract-plugin": "^2.9.0"
}
}

View File

@ -0,0 +1,43 @@
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/** @type {import("../../../../types").Configuration} */
module.exports = {
devtool: false,
target: "web",
entry: "./index.js",
mode: "development",
optimization: {
concatenateModules: false
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader",
options: {
esModule: true,
modules: {
namedExport: false,
localIdentName: "[name]"
}
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css"
})
],
node: {
__dirname: false,
__filename: false
}
};