webpack css-loader localIdent name hash length

2019-08-24 02:39发布

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条回答
爷、活的狠高调
2楼-- · 2019-08-24 03:33

finally I find the right way, it is hash, not randomNamingfunction. 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.

查看更多
登录 后发表回答