1-classname 中文文档教程
1-classname
生成一位数字类名及更多。
Why
与其使用创建不必要的长类名的传统 css 类名散列,不如使用一位数字类名策略将类名减少到仅 1 个字节。
hashing | example | byte / class | |
---|---|---|---|
traditional hash | [path][name]__[local]--[hash:base64:5] | cssmain__anyLocal--YWtkd | at least 8 byte |
one digit | [a-Z] | a | 1 |
假设平均传统哈希的平均长度为 16,并且有大约 300 个类并且使用了 id:
// Traditional Hash
16 * 300 // 4,800 byte used
// one digit hash
( 52 * 1 ) / ( (300 - 52) * 2) // 548 byte used
// For further explaination, please visit 'one digit hashing' section below.
通过使用 1-classname,我们将 classname 单独使用的字节减少了 8.75x
Note
虽然传统的 css 类名确保类名永远不会重复,但使用“一个类名”(此模块)你有确保 className 永远不会被自己复制。 您可能想使用传统的哈希,然后使用一个类名来缩短它,如下所示:
import hash from '1-clasname'
hash(`${getPathAndNameAndClassNameSomehow()}`) // cssmain__anyLocal--YWtkd => a
现在我们 100% 唯一的一位数类名并减少包大小。
One digit hashing
一个数字是减少长散列的策略className 只保留 1 位数字。 如果全部使用一位数,则使用两位数,依此类推。 注意:虽然理论上我们可以对所有类名使用一个数字(例如:表情符号、ASCII 字符),但我们希望遵循 className 的 w3 标准。 这意味着它并不总是一位数,但总是有效的 w3 标准一位数。
这将有助于将长类名减少为短类名,从而减少大量的包大小。
序列可以描述如下:
range | digit | possible classname |
---|---|---|
1-52 | 1 | a-Z |
53-2756 | 2 | aa-ZZ |
2757-243363 | 3 | aaa-ZZZ |
and so on | n | n([a-Z]) |
或举例说明如下:
index | 0 | 1 | 2 | 3 | 25 | 26 | 27 | 51 | 52 | 53 | 78 | 79 | 103 | 104 | 105 | 2755 | 2756 | 2757 | 143362 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
character | a | b | c | d | z | A | B | Z | aa | ab | aA | aB | aZ | ba | bb | ZZ | aaa | aab | ZZZ |
随着范围的增加,可以使用斐波那契数列描述如下:
const generateLimit = (digits: number) => {
if (digits === 0) return 0
return 52 ** digits + generateLimit(digits - 1)
}
const limit = generateLimit(digits) - (digits - 1)
当className为hash时,将作为key存储在object中如下:
{
[key-1]: "a",
[key-2]: "b"
[key-3]: "c"
}
即第二次调用该类时,不会生成新的类名,而是使用旧的类名。
Getting started
只需使用 yarn 或 npm 安装即可。
yarn add 1-classname
// or with npm
npm install 1-classname
一个类名具有内置的 TypeScript 支持,这意味着不需要 @types/1-classname
。
Usage
该库旨在与 css-loader 的 localIdentName
一起使用。
以下代码演示如何减少 .module.sass
文件的类名。
cssLoaderOptions: {
getLocalIdent: (
loaderContext,
localIdentName,
localName,
options
) => {
const filePath = loaderContext.resourcePath
const fileBaseName = basename(filePath)
if (/\.module\.sass$/.test(fileBaseName)) {
const modulePathParts = filePath.split('/')
const moduleName =
modulePathParts[modulePathParts.length - 2]
return `_${oneClassName(moduleName + localName)}`
}
return localName
}
}
如果你想要前缀,你可以使用模板文字:
generateLocalIdentSomehow: (string) => `${generatePrefixSomehow()}-${hash(string)}`,
Contribution
欢迎所有贡献、讨论和 PR。
如果您有任何问题,请随时在 issue 提问
1-classname
Generate one digit classname and beyond.
Why
Instead of using traditional css classname hashing which created unnecessary long className, using one digit classname strategy reduce className to only 1 byte.
hashing | example | byte / class | |
---|---|---|---|
traditional hash | [path][name]__[local]--[hash:base64:5] | cssmain__anyLocal--YWtkd | at least 8 byte |
one digit | [a-Z] | a | 1 |
Let's say if average tranditional hash has an average length of 16 and there's about 300 classes and id is used:
// Traditional Hash
16 * 300 // 4,800 byte used
// one digit hash
( 52 * 1 ) / ( (300 - 52) * 2) // 548 byte used
// For further explaination, please visit 'one digit hashing' section below.
By using 1-classname, we reduce byte used by classname alone by 8.75x
Note
Although traditional css classname ensure that className will never be duplicated, using 'one classname' (this module) you have to make sure that className will never be duplicated by yourself. You might wanted to use traditional hash then use one className to shorten it as the following:
import hash from '1-clasname'
hash(`${getPathAndNameAndClassNameSomehow()}`) // cssmain__anyLocal--YWtkd => a
Now we 100% unique one digit className and decrease bundle size.
One digit hashing
One digit is strategy to reduce long hash className to 1 digit only. If all one digit is used, it will use 2 digits and so on. Note: Although, theotically we can use one digit for all className (ex: emoji, ASCII character), we want to follow w3 standard for className. Which means it not really always one digit but always valid w3 standard one digit.
This will helps reduce long className into short one thus reduce a lot of bundle size.
The sequence can be describe as the following:
range | digit | possible classname |
---|---|---|
1-52 | 1 | a-Z |
53-2756 | 2 | aa-ZZ |
2757-243363 | 3 | aaa-ZZZ |
and so on | n | n([a-Z]) |
or illustration as example as the following:
index | 0 | 1 | 2 | 3 | 25 | 26 | 27 | 51 | 52 | 53 | 78 | 79 | 103 | 104 | 105 | 2755 | 2756 | 2757 | 143362 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
character | a | b | c | d | z | A | B | Z | aa | ab | aA | aB | aZ | ba | bb | ZZ | aaa | aab | ZZZ |
As the range goes on, it can be describe by using fibonacci sequence as the following:
const generateLimit = (digits: number) => {
if (digits === 0) return 0
return 52 ** digits + generateLimit(digits - 1)
}
const limit = generateLimit(digits) - (digits - 1)
When the className is hash, it'll be stored as key in object as the following:
{
[key-1]: "a",
[key-2]: "b"
[key-3]: "c"
}
Which means when the class is called after the second time, it will not generate new className but rather using old one.
Getting started
Simply install with yarn or npm.
yarn add 1-classname
// or with npm
npm install 1-classname
One classname has built-in TypeScript supports which means no @types/1-classname
is need.
Usage
This library is designed to be used with localIdentName
of css-loader.
The following code demonstrate how to reduce className of .module.sass
file.
cssLoaderOptions: {
getLocalIdent: (
loaderContext,
localIdentName,
localName,
options
) => {
const filePath = loaderContext.resourcePath
const fileBaseName = basename(filePath)
if (/\.module\.sass$/.test(fileBaseName)) {
const modulePathParts = filePath.split('/')
const moduleName =
modulePathParts[modulePathParts.length - 2]
return `_${oneClassName(moduleName + localName)}`
}
return localName
}
}
If you want prefix you can use template literal:
generateLocalIdentSomehow: (string) => `${generatePrefixSomehow()}-${hash(string)}`,
Contribution
All contribution, discussion and PR is welcome.
If you have any questions, feels free to ask at issue