问题
I use webpack
and css-loader
, and in my css-loader
config I use these options:
options: {
importLoaders: 1,
modules: true,
localIdentName: '[hash:base64:3]'
}
Just like you see, it is obvious that I desire all of my class name will have 3 characters, and after build absolutely my desire come true but there is a very big issue.
Some class names has same name! (conflict!)
for example:
._1mk { /*dev name was .home*/
color: red;
} /*line 90*/
and
._1mk { /*dev name was .news*/
color: blue;
}
This is a big issue, but when I use [hash:base64:5]
everything would be ok and each class has its own hash name without any conflict.
I search this issue about 4 hours and saw all developers use number 5 as less of length of hash for their config. I don't know why! I calculate that 64 characters [a-z][A-Z][0-9][-,_] in three length can has 262144 different words, so why it can not some different names?
how can I settle this conflict? Really should I miss the number 3 ? and use 5 like others?
回答1:
finally I find the right way, it is hash
, not randomNaming
function. this is made to hash so it is so obviously in short length with vast naming maybe it produce collision. so I write my own webpack
naming function and use the variables and the function top on webpack
config file. these are steps of my solution:
At first, two variables for cache
and queue
. cache for easy accessing to LocalName
and its new randomName
and queue for holding variable entries that involve all new random names for avoiding collision.
let q = [],
cache = {};
At second, we declare randomNaming
function. I know, maybe it is not very optimize but it works well. the export file is awesome without any collision.
function randomNaming(length,limit) {
let result = '',
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
/*All valid chars*/
fchars = 'abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
/*All valid first chars*/
do {
if (q.length >= (52 * Math.pow(64, limit - 1)) && limit >= length) {
return 'OutOfPossibility';
} else if (q.length >= (52 * Math.pow(64, limit - 1)) && limit < length) {
++limit;
}
result = '';
result += fchars[Math.floor(Math.random() * fchars.length)];
for (let i = limit - 1; i > 0; --i) {
result += chars[Math.floor(Math.random() * chars.length)];
}
} while (q.includes(result));
q.push(result); /*push for avoiding collision in next time of funtion call*/
return result;
}
At Third, in css-loader
scope inside of webpack
config I used getLocalIdent
not localIdentName
.
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
var randName = randomNaming(3,2);
if (localName.match(/^i-/i)) {
randName = `i-${randName}`;
} else if (localName.match(/^i_/i)) {
randName = `i_`;
} else {
randName = `${randName}`;
}
if (typeof cache[localName] =='undefined') {
cache[localName] = randName;
return cache[localName];
} else {
return cache[localName];
}
}
And now all of names are hashed and CSS
file is in minimal possible volume size. And the HTML
is so light weight.
来源:https://stackoverflow.com/questions/47580113/webpack-css-loader-localident-name-hash-length