Reputation: 32572
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?
Upvotes: 1
Views: 1287
Reputation: 32572
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 produces a collision. so I write my own Webpack
naming function and use the variables and the function top on the Webpack
config file. these are the 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 a collision.
let q = [],
cache = {};
Second, we declare the randomNaming
function. I know, maybe it is not very optimized 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
.
const 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 the names are hashed and the CSS
file is in minimal possible volume size. And the HTML
is so lightweight.
Upvotes: 3