webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.67k stars 389 forks source link

Bad CSS order for external packages with `"sideEffects": ["*.css"]` #1070

Closed kosciolek closed 10 months ago

kosciolek commented 10 months ago

Bug report

Actual Behavior

Classes should be loaded in the order of imports. Therefore this:

import { MyComponent } from 'my-monorepo-subpackage-or-npm-package';
import './my-styles.css'

Should become:

.myComponentClass {}
.myStylesClass {}

However, sometimes it becomes:

.myStylesClass {}
.myComponentClass {}

Webpack reorders imports of side effect free modules during compilation. However, you can stop the reordering by setting "sideEffects": [ "*.css" ] in package.json.

The directive works for the main package in which your application resides. However, the directive does not work, when it's declared in an imported package (i.e. 3rd party packages, or other packages in your monorepo). If you have my-child-package/package.json with "sideEffects": [ "*.css" ], then webpack might mess up the class order.

The directive seems to work on some level, as it will stop CSS from being tree shaken out completely, so the classes will be included, but they will not be included in the proper order.

Expected Behavior

Classes in main.css should appear in the order of imports:

.myComponentClass {}
.myStylesClass {}

This is important, as:

  1. It makes sense for you to override a 3rd party package's styles, not the other way around.
  2. Components built on top of other components (which they import) should be able to override their styles. If you have a TextArea built on top of an Input, then TextArea's styles should be more important.

I understand it's best not to rely on CSS order between different files and it cannot always be resolved properly, but this looks like a bug that's easily solvable and quite important for monorepos.

How Do We Reproduce?

https://github.com/kosciolek/webpack-css-order-reproduction

  1. Install deps with yarn.
  2. yarn webpack
  3. View dist/main.css

Please paste the results of npx webpack-cli info here, and mention other relevant information

Runs on WSL 2 inside win11

  System:
    OS: Linux 5.10 Ubuntu 20.04.6 LTS (Focal Fossa)
    CPU: (24) x64 AMD Ryzen 9 3900X 12-Core Processor
    Memory: 8.60 GB / 15.60 GB
  Binaries:
    Node: 20.9.0 - ~/.nvm/versions/node/v20.9.0/bin/node
    Yarn: 4.0.2 - /mnt/c/Users/rijndael/AppData/Roaming/npm/yarn
    npm: 10.1.0 - ~/.nvm/versions/node/v20.9.0/bin/npm
  Packages:
    css-loader: ^6.8.1 => 6.8.1 
    webpack: ^5.89.0 => 5.89.0 
    webpack-cli: ^5.1.4 => 5.1.4 

Might be a webpack problem, since this plugin seems to just follow the postorder order of modules in webpack's chunk graph. Please let me know if I should move this issue to the webpack repo instead. I added some console.log's, the order of imports is already messed up at this point https://github.com/webpack-contrib/mini-css-extract-plugin/blob/f576ed6a530db555d7442ebab1f9a09f3acff13f/src/index.js#L1190

Might be related to https://github.com/webpack/webpack/issues/7094, but it's an old issue that a) doesn't talk about external packages, whereas this issue applies only to external packages b) for some people there styles are missing altogether, instead of just being in bad order

alexander-akait commented 10 months ago

Yeah, it is a bug in webpack, here details about it https://github.com/webpack/webpack/issues/7094#issuecomment-945663737, I want to close it, because we can't solve it here, also I will add a priority to this issue