Hey everyone, just sharing a problem I found, to see if I'm missing something or if the suggested improvement could be a good idea.
If you go with the default options, or define your own localIdentName, the generated hash, without a hashPrefix, will be a digest of the relative path and the local classname.
This causes collision when you have two separate modules built with webpack that have a file with the same path, with the same classname in it (both modules have src/blah/styles.scss with the class .classname in it)
To solve this collision, I added a hashPrefix to the query, making it random on each build (something like <package-name> + Date.now() works great).
Isn't it a good idea to make a random hashPrefix be default behaviour?
Running into the same issue. Any advice would be much appreciated.
@claudiorodriguez do you have an example for your solution? Running into this as well.
@AdamJo @jeffijoe the easiest workaround is to add hashPrefix to your css-loader query, e.g.
{
loader: 'css-loader',
query: {
hashPrefix: 'package-name' + Date.now()
localIdentName: [local]_[hash:base64:5],
modules: true
}
}
@claudiorodriguez oh okay! I was looking through docs to see if I could find any hashPrefix variable anywhere but I couldn't - isn't this documented?
I think it's undocumented. It's used here https://github.com/webpack-contrib/css-loader/blob/master/lib/getLocalIdent.js#L12
Damn, I looked at that file for like 10 minutes and I didn't spot that - @claudiorodriguez thank you!
If you are use LoaderOptionsPlugin, then you can add context
new webpack.LoaderOptionsPlugin({
options: {
context: __dirname,
...
classes will be unique
@mitkaaa thanks, this works for me. but could you please explain why this would solve this issue?
Agree @mitkaaa i'm a bit confused by the solution... is this global config or local to css loader?
I think you can set context to __dirname on the options object passed in to css-loader, you shouldn't need to use LoaderOptionsPlugin.
@plrthink @dcworldwide I believe this works because css-loader uses the value of options.context when generating the hash used in the localIdentName. By default context is just the local directory name of the module but by setting it to __dirname it includes the full absolute system path to that module, e.g. '/Users/bob/example' instead of just 'example', resulting in a different hash each time.
Won't __dirname just set it to the path of the webpack config?
Yeah, you're right. Seems to work anyway. ¯_(ツ)_/¯ Will try and dig into it further at some point.
__dirname is not resolved when webpack loads. Its tucked away in a lazy function (getLocalIdent) that gets evaluated when a css file is bring processed. So it'll point to correct path everytime.
If you specify context: __dirname in your webpack config, then it _should_ be evaluated when webpack loads: https://nodejs.org/docs/latest/api/globals.html#globals_dirname
__dirname is set In webpack config to the config's file path but getLocalIdent then resolves the relative path from there to the stylesheet, thereby generating a unique string for each for use in the hashing algorithm.
Ah, I see. My bad.
@mitkaaa you saved me!
Feel free to documentation this!
Got same problem after moving to webpack-4.0.0beta. Updating css-loader with context fix this issue for me too. Config example:
{ loader: 'css-loader',
options: {
modules: true,
context: __dirname,
localIdentName: '[local]-[hash:base64:6]',
}
Thanks so much for this solution!
I've opened a PR to refer this problem and workaround in docs https://github.com/webpack-contrib/css-loader/pull/770
Somebody can create minimum reproducible test repo?
Closing due impossible reproduce. Feel free to create new issue if you faced with problem. Thanks!
Most helpful comment
If you are use LoaderOptionsPlugin, then you can add context
classes will be unique