像 google 一样通过缩短 css 类名和作用域隔离来压缩优化 css 包的大小

像 google 一样通过缩短 css 类名和作用域隔离来压缩优化 css 包的大小

就像 google 的做法一样

今年年初,我已经退出咨询公司并开始构建 GO2CINEMA - 一个 快速,简单和安全 的方式来预订英国的电影票的网站。我做了一个辉煌的工作,使其快速,简单和安全。在其中某个阶段,我一直痴迷于关键渲染路径的优化。⚡️

我已经使用 ūsus 解决了 HTML 的预渲染。ūsus 渲染单页应用程序(SPA)的 HTML,并内嵌了用于呈现页面的 CSS。但是,我并不喜欢在每个 HTML 文档内嵌 70 KB 的 css,特别是其中大部分是 CSS 类名。

就像Google一样

你有没有看过 https://www.google.com/ 的源代码?如果看过,您注意到的第一件事是会是,CSS 类名称没有超过几个字符。

https://cdn-images-1.medium.com/max/800/1*mGuDYFM56iyLi1MgZPC8bw.png

但是怎么样做到的呢?

CSS minifiers 的缺点

有一件事,minifier 不能做 - 改变选择器名称。这是因为 CSS minifier 不能控制 HTML 输出。同时,CSS 名称可以很长。

如果您使用 CSS modules,您的 CSS modules 可能会包含样式表文件名,本地标识名和随机哈希。使用 css-loader localIdentName 配置描述类名模板,例如[name]___[local]___[hash:base64:5]。因此,生成的类名称将如下所示 .MovieView___movie-title___yvKVV ; 如果你喜欢描述性的名字,它可能更长,例如 .MovieView___movie-description-with-summary-paragraph___yvKVV

在编译时重命名 CSS 类名

但是,如果您使用的是 webpackbabel-plugin-react-css-modules,那么您很幸运 🍀 - 您可以使用 css-loadergetLocalIdent 配置项或者等效的 babel-plugin-react-css-modules 中的 generateScopedName 配置项来达到在编译时重命名类名的目的。

generateScopedName 中很酷的是,同样的功能实例可以用于 Babelwebpack 的构建过程:

让名字变短

感谢 babel-plugin-react-css-modulescss-loader 共享相同的逻辑来生成 CSS 类名称,我们可以将类名改为任何我们喜欢的,甚至是随机哈希。然而,我想要最短的类名,而不是随机哈希。

为了生成最短的类名,我创建了类名索引,并使用该 incstr 模块为索引中的每个条目生成增量ID。

这保证了类名简短并且唯一。现在,.MovieView___movie-title___yvKVV.MovieView___movie-description-with-summary-paragraph___yvKVV 的类名都成了 .a_a, .b_a等。

这将 GO2CINEMA CSS 压缩包的大小从 140 KB 降低到 53KB。

使用作用域隔离来进一步减少包的大小

分离组件名称和本地标识符名称是一个很好的理由让我添加 _ 到 CSS 类名 - 对于缩小文件大小特别有用。

csso(CSS minifier)具有作用域配置。作用域定义了在某些标记上专门使用的类名列表,即来自不同作用域的选择器不会匹配同一个元素。这一条让优化规则更进一步。

要利用此功能,请使用 csso-webpack-plugin 来后处理 CSS 包:

这使 GO2CINEMA CSS 捆绑包的大小从 53 KB 降至 47 KB。

这值得么?

这种压缩的第一个争议是觉得压缩算法本来就可以做到。使用 Brotli 算法压缩的 GO2CINEMA CSS 包与长类名的原始包相比只压缩了 1 KB。

另一方面,设置这个缩小是一次性投入,它减少了需要解析的文档的大小。它还具有其他好处,例如阻止依赖 CSS类名称的扫描仪导航或意外匹配广告拦截器黑名单的 CSS选择器。

同时,您可以看到在 GO2CINEMA 和 venue 页面上使用的这种压缩的演示,例如

【翻译原文】:https://medium.freecodecamp.org/reducing-css-bundle-size-70-by-cutting-the-class-names-and-using-scope-isolation-625440de600b

0%