vue-loader
vue-loader copied to clipboard
CSS Modules "сustom Inject name" it works incorrectly (lost index)
Version
15.7.1
Reproduction link
https://github.com/PowerfulPony/vue-loader-css-modules-mixing-selector-error
App.vue
<template>
<div id="app">
<div :class="cssModuleA.root">Module A: Green</div>
<div :class="cssModuleA.uniqNameA">Uniq A: Green</div>
<div :class="cssModuleB.root">Module B: Yellow</div>
<div :class="cssModuleB.uniqNameB">Uniq B: Yellow</div>
<div :class="cssModuleC.root">Module C: Red</div>
<div :class="cssModuleC.uniqNameC">Uniq C: Red</div>
</div>
</template>
<style module="cssModuleA">
.root {
background: green;
}
.uniqNameA {
background: green;
}
</style>
<style module="cssModuleB">
.root {
background: yellow;
}
.uniqNameB {
background: yellow;
}
</style>
<style module="cssModuleC">
.root {
background: red;
}
.uniqNameC {
background: red;
}
</style>
Steps to reproduce
- Create module A, place a selector with the name X in it.
- Create module B, place a selector with the name X in it.
What is expected?
It is expected that the name for the A.X class will be Hash_0
, and for the B.X class Hash_1
. So it was in version 14. *
<div id="app">
<div class="App_root_1N-C8_0">Module A: Green</div>
<div class="App_uniqNameA_1Obkq_0">Uniq A: Green</div>
<div class="App_root_1N-C8_1">Module B: Yellow</div>
<div class="App_uniqNameB_cJTiO_1">Uniq B: Yellow</div>
<div class="App_root_1N-C8_2">Module C: Red</div>
<div class="App_uniqNameC_X4xZM_2">Uniq C: Red</div>
</div>
What is actually happening?
The names of the output selectors are identical Hash
.
<div id="app">
<div class="App_root_1N-C8">Module A: Green</div>
<div class="App_uniqNameA_1Obkq">Uniq A: Green</div>
<div class="App_root_1N-C8">Module B: Yellow</div>
<div class="App_uniqNameB_cJTiO">Uniq B: Yellow</div>
<div class="App_root_1N-C8">Module C: Red</div>
<div class="App_uniqNameC_X4xZM">Uniq C: Red</div>
</div>
Because of this, it is impossible to use different modules in the same vue file, with identical class names. Since, according to the cascade, the rules described in both cases will overlap.
https://vue-loader.vuejs.org/guide/css-modules.html#custom-inject-name
I encountered this problem when I decided to update the project on vue-cli 3. *, since it uses 15. * version
Incorrect operation can be seen in the attached repository. For clarity, 6 elements with different colors are used, 3 of which have the same class (although it should be different).
I noticed that the modules work out correctly, but due to the lack of an index, a cascade occurs.
I did not find a quick way to return a lost index to the output.
Using localIdentName
[N]
also does not fix the problem.
Maybe someone will need a temporary solution that is close to the original getLocalIdent
but has index
and module
at its disposal
loaderOptions
css: {
localIdentName: '[path][name][module]-[local]-[hash:base26:5]',
getLocalIdent(context, localIdentName, localName) {
const { resourceQuery, resourcePath } = context;
const { index, module } = loaderUtils.parseQuery(resourceQuery);
const selector = loaderUtils.interpolateName(context, localIdentName, {
context: context.rootContext,
content: resourcePath + resourceQuery + localName,
})
.replace(/\[local\]/gi, localName)
.replace(/\[module\]/gi, typeof module === 'boolean' ? '' : module)
.replace(/\[index\]/gi, index)
.replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-')
.replace(/^((-?[0-9])|--)/, '_$1');
return selector;
},
}
in version 14, the index was passed to helpers.js
here
https://github.com/vuejs/vue-loader/blob/v14/lib/helpers.js#L254
I think the thing helpers.js
did, can be achieved in the genCSSModulesCode
function: https://github.com/vuejs/vue-loader/blob/master/lib/codegen/styleInjection.js#L32
I have the same issue, is there any solution for version 15.9.8?
This seems to be a config for css-loader?!
Maybe someone will need a temporary solution that is close to the original
getLocalIdent
but hasindex
andmodule
at its disposal
loaderOptions
css: { localIdentName: '[path][name][module]-[local]-[hash:base26:5]', getLocalIdent(context, localIdentName, localName) { const { resourceQuery, resourcePath } = context; const { index, module } = loaderUtils.parseQuery(resourceQuery); const selector = loaderUtils.interpolateName(context, localIdentName, { context: context.rootContext, content: resourcePath + resourceQuery + localName, }) .replace(/\[local\]/gi, localName) .replace(/\[module\]/gi, typeof module === 'boolean' ? '' : module) .replace(/\[index\]/gi, index) .replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-') .replace(/^((-?[0-9])|--)/, '_$1'); return selector; }, }