Skip to content

SSR: generated class names are not consistent for client and server bundles since v5.1.3 #1384

@OliverJAsh

Description

@OliverJAsh

Bug report

We are using css-loader with server-side rendering (SSR), so we run webpack twice: once for the client and once for the server.

For the client, we need to generate CSS files, so we use mini-css-extract-plugin in combination with css-loader.

For the server, we don't need to generate CSS files, so we use exportOnlyLocals: true. We just need the CSS modules to export the same class names as the ones used in the CSS files we generated for the client (above).

Actual Behavior

Generated class names are not consistent for client and server bundles.

Expected Behavior

Generated class names are consistent for client and server bundles.

How Do We Reproduce?

Full reduced test case: https://github.com/OliverJAsh/webpack-css-loader-ident-hash-bug

package.json:

{
  "dependencies": {
    "css-loader": "^6.3.0",
    "mini-css-extract-plugin": "^2.4.2",
    "webpack": "^5.58.1",
    "webpack-cli": "^4.9.0"
  }
}

webpack.config.js:

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

const { MODE } = process.env;

module.exports = {
    plugins: [new MiniCssExtractPlugin()],
    mode: "production",
    entry: "./src/main.js",
    module: {
        rules: [
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: [
                    ...(MODE === "client" ? [MiniCssExtractPlugin.loader] : []),
                    {
                        loader: "css-loader",
                        options: {
                            modules: {
                                exportOnlyLocals: MODE === "server",
                            },
                        },
                    },
                ],
            },
        ],
    },
};

src/main.js:

import styles from './main.css'
console.log(styles.container);

src/main.css:

.container {
    display: block;
}

Since this change which first appeared in v5.1.3, css-loader generates different class names for the client/server:

$ rm -rf dist && MODE=client webpack && node dist/main.js
UgjPTt4sSFtvFL9kN_LV

$ rm -rf dist && MODE=server webpack && node dist/main.js
BZjOBwj614XLb60af45_

It seems this is because css-loader now uses relativeMatchResource as part of the hash, and in this case, relativeMatchResource will be different depending on whether or not we're using mini-css-extract-plugin:

  • MODE=server (mini-css-extract-plugin is used): relativeMatchResource is ''
  • MODE=client (mini-css-extract-plugin is not used): relativeMatchResource is 'src/main.css\x00'

We are able to workaround the issue by downgrading to v5.1.2 which does not include this change.

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

  System:
    OS: macOS 11.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 3.09 GB / 16.00 GB
  Binaries:
    Node: 16.3.0 - ~/.nvm/versions/node/v16.3.0/bin/node
    Yarn: 1.19.1 - /usr/local/bin/yarn
    npm: 7.15.1 - ~/.nvm/versions/node/v16.3.0/bin/npm
  Browsers:
    Chrome: 94.0.4606.71
    Chrome Canary: 96.0.4664.2
    Firefox: 90.0.2
    Firefox Nightly: 77.0a1
    Safari: 15.0
    Safari Technology Preview: 15.4
  Packages:
    css-loader: ^6.3.0 => 6.3.0
    webpack: ^5.58.1 => 5.58.1
    webpack-cli: ^4.9.0 => 4.9.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions