如何减小包大小-CSS模块中的单字母类策略

通过将标准哈希替换为一个字母前缀+文件路径的哈希,我们将文件包的压缩提高了文件大小的40%。

CSS模块允许您编写Bird和Cat组件,并在文件中使用具有相同样式的文件中的样式,每个样式都具有styles.css和.block类,并且这些类对于每个组件而言都是不同的。

/* Bird / styles.css */
.block { }
.name { }
/* Cat / styles.css */
.block { }
.name { }

这里没有什么棘手的问题:Webpack使用“ [hash:base64:8]”设置对所有文件中的每个类进行哈希处理。所有的类都将被重命名,并添加链接以了解哪个类来自。在程序集的基本版本中,当使用js时,我们将具有用于样式的styles.css文件和用于链接的styles.js。

继续测试用例,我们得到了4个独立的类,它们的名称很奇怪,例如k3bvEft8:

/* Bird */
.k3bvEft8 { }
.f2tp3lA9 { }
/* Cat */
.epIUQ_6W { }
.oRzvA1Gb { }

运行生产程序集并压缩文件。在展位上,使用gzip将300Kb css文件打包为70Kb [使用brotli将其打包为50Kb]。压缩量很小,因为哈希是随机生成的字符串,压缩效果很差。压缩算法看不到序列,并且被迫记住每个符号的位置,即 无需压缩即可直接传输这些部分的内容。

这需要做一些事情。但是呢 在操作过程中,Webpack异步读取文件树,并且还会遍历类名。每次以不同的方式。您唯一可以坚持的是css中名称的顺序-它是常量(否则,所有内容都会中断,在css中,顺序很重要)。文件中的类位置编号以一个字母开头的前缀编码。您可以采用52([a-zA-Z] +)或64([a-zA-Z0-9 _-] +)字符进行编码。最主要的是不要忘记在带有数字或连字符的情况下放下保护性前缀。

/* Bird */
.a { }
.b { }
/* Cat */
.c { }
.d { }

看起来不错-名称已尽可能压缩。但是要注意的是,Webpack是异步的,并且每次启动时,尤其是在同时启动服务器和客户端并发程序集时,都会像类名一样以混乱的方式接收文件。感谢您的速度,但在这里会造成干扰。

/* Bird */
.c { }
.d { }
/* Cat */
.a { }
.b { }

您看,发现文件顺序不匹配。

我们通过记住文件,类的来源及其位置编号来解决此问题。

/* Bird */
.a { }
.b { }
/* Cat */
.a { }
.b { }

将订单保存在文件中。但是您需要以某种方式将文件彼此区分开。文件路径中的哈希将有助于避免混淆。

/* Bird */
.a_k3bvEft8 { }
.b_k3bvEft8 { }
/* Cat */
.a_oRzvA1Gb { }
.b_oRzvA1Gb { }

(这里不需要'_',仅用于说明目的。散列具有稳定的长度,与前缀不同,并且不存在冲突)。

我们获得了对于项目绝对唯一但包含重复序列的类名。

在我们的项目中,从文件css 50 Kb和js 47 Kb中我们得到了css 30 Kb和js 28 Kb [总共58 Kb,brotli]。
节省近40Kb。关键CSS的大小和html的大小将略有减少。

仍然需要编写一个类来处理来自Webpack的数据,并在css-loader配置(getLocalIdent)中引发调用

PS您可以走得更远并保存文件路径,对路径进行排序并使用单字母策略替换它们,但是就长期缓存而言,这种情况会更糟,此外,您还需要在组装过程中多次通过并按顺序组装客户机/服务器。

PS2 如果您在此处使用代码

PS3 ,现在可以尝试您的项目,在生产中,我们将* .css和* style.js文件压缩93%。我们从已解压缩文件的1,1Mb(brotli)转移了71,6Kb

All Articles