Skip to content

The order of CSS imports is not respected #465

@iamakulov

Description

@iamakulov

Not sure whether this is related to #399 or a separate issue.

Test case

Consider the following project:

// index.js
import "./transitive-import.js"
import "./b.css"
import "./a.css"

console.log("foo")

// transitive-import.js
import "./c.css"
/* a.css */
body {
  color: blue;
}

/* b.css */
body {
  color: red;
}

/* c.css */
body {
  color: green;
}

Actual behavior

If you bundle the project with ESBuild:

npx esbuild ./index.js --bundle --outdir=./build

the resulting build/index.css file will look as follows:

/*** build/index.css ***/
/* a.css */
body {
  color: blue;
}

/* b.css */
body {
  color: red;
}

/* c.css */
body {
  color: green;
}

The problem here is that ESBuild changes the order of CSS modules. This changes the specificity of rules – and, ultimately, changes how the page would look. (The text would be green instead of blue.)

Expected behavior

The expected behavior is for ESBuild to bundle CSS imports in the order of their appearance in the module tree (with depth-first traversal). That’s how webpack does that (AFAIK).

You can test the webpack behavior with the following config:

Details

package.json:

{
  "name": "test",
  "version": "1.0.0",
  "dependencies": {
    "css-loader": "5.0.0",
    "mini-css-extract-plugin": "1.0.0",
    "webpack": "5.1.3",
    "webpack-cli": "^4.0.0"
  }
}

webpack.config.js:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./index.js",
  output: {
    path: __dirname + "/build",
    filename: "[name].js"
  },
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"]
      }
    ]
  }
};

Building the project with the above config (npx webpack) produces build/main.css that looks as follows:

body {
  color: green;
}

body {
  color: red;
}

body {
  color: blue;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions