给前端以福利,给编程以复利。大家好,我是大家的林语冰。
00. 观前须知
地球人都知道,CSS minify(压缩/简化)有助于提高网站性能。但如今我们好像对 CSS minify 绝口不提。这一切的背后究竟是道德的沦丧,还是人性的扭曲?
Vite 制霸前端工具领域之前,建立一个全新的前端项目需要浪费数小时,手动配置 Grunt 或 Gulp 文件,编译、压缩和后处理 CSS 文件,这样苦逼的日子如今总算一去不复返了!
CSS 的高性能交付一般诉诸 HTTP/2 和现代压缩算法来搞定,而现代前端框架则负责其他优化,例如代码分割和压缩。
简而言之,CSS 优化可以通过现代前端工具大幅改良,所以 CSS minify 已经不再是前端工程化的顽瘴痼疾。
免责声明
本文属于是语冰的直男翻译了属于是,略有删改,仅供粉丝参考。英文原味版请传送 Why don't we talk about minifying CSS anymore?。
01. 我们为什么需要 CSS minify?
CSS minify 是删除所有冗余空格的机制,这使 CSS 文件的体积更精简,但浏览器仍然可以准确解析这些样式。
简而言之,CSS minify 可以优化 FCP(首次内容绘制)。FCP 是一个核心的 Web 性能指标,用于测量网页的感知加载速度,它标志着页面加载期间,用户可以看到屏幕上任何内容的第一个时间点。
FCP 的分数及格线是小于等于 1.8
秒,这让用户不必焦虑等待正在加载的网页。为了确保优秀的 FCP 跑分,你的样式表或内联 CSS 应尽量精简,这样下载 CSS 耗时更少,且可以更快处理,从而允许浏览器快速在页面上绘制内容。
这也有助于优化 关键渲染路径(critical render path),即浏览器将 HTML、CSS 和 JS 转换为屏幕像素的完整执行步骤,这对于网速较慢的用户而言至关重要。
此外,CSS 是一种渲染阻塞资源,这意味着,在下载 CSS 并结合 DOM 构建 CSSOM(CSS 对象模型)之前,浏览器不会展示任何内容。
另外,如果在页面上渲染 HTML 之后加载并应用 CSS,则在应用 CSS 规则之前,用户将体验到无样式内容的屏闪。
加载内容后,绘制样式和回流重排也可能会影响用户体验。样式表中提供的 CSS 以及页面 <head>
标记中的内联 CSS 都会阻塞渲染。
02. CSS minify 工具
前端开发有许多工具支持 CSS minify,或作为构建管道的一部分,包括但不限于 cssnano
和 Vite。
你简化后的 CSS 体积可能会有所出入,具体取决于 CSS 的复杂性,但你可能会见证诸如此类的优化数据:
原始体积(kB) | 压缩体积(kB) | 优化体积(kB) |
---|---|---|
78 | 65 | 13 |
有趣的是,这些优化跟存储在磁盘上的文件有关,从服务器传送的文件实际上会小得多。
03. 现代 HTTP 压缩算法
Web 服务器和浏览器等客户端使用 HTTP 压缩,来提高资源的传输速度,且有助于节省带宽成本和管理费用。目前有许多可用的压缩算法,但现代浏览器无法支持所有算法。
服务器可能支持多种压缩类型,目前网络上最常用的压缩类型是 gzip 和 Brotli。
当发出 HTTP 请求时,浏览器告诉服务器它们能够解码的压缩方法,此时服务器会发送合适的压缩文件版本。不支持压缩方法的浏览器则将收到未压缩的数据。
你可以在浏览器开发工具中检查网络请求的 HTTP 请求和响应首部,举个栗子:
请求首部(发送到服务器):
- Accept-Encoding(接受编码)列出客户端/浏览器支持的压缩方法
响应头(从服务器接收):
- Content-Encoding(内容编码)描述用于解码传输数据的压缩方法
- Content-Length(内容长度)提供压缩文件的大小(单位为字节)
如果你使用 Sentry 工具来监测应用程序,你还可以检查关联范围中每个网络请求的响应首部。
有趣的是,非简化压缩文件和简化压缩文件的体积优化并不明显,有时甚至只优化了 1kB。
CSS 文件 | 原始体积(kB) | 压缩体积(kB) | 优化体积(kB) |
---|---|---|---|
磁盘文件 | 78 | 65 | 13 |
压缩文件 | 11 | 10 | 1 |
虽然 1kB 看起来无关痛痒,但节省的成本绝对会让你和你的用户受益匪浅。
截至 2024 年,全球移动互联网速度中位数为 52.98Mbps。虽然这相当于每秒能够下载 6625kB,但如果你可以从每个页面加载的总共 100 个资源中仅减少 1kB,那么用户的页面速度可以提高 15 毫秒。
同时,作为开发者或组织,你将节省带宽成本。虽然对于单个用户而言 1kB 并不算多,但对于 1000 个用户而言,这相当于少传输 1MB 的数据。
04. HTTP/2 多路复用
CSS minify 逐渐退出历史舞台的另一个进步是 HTTP/2。
HTTP/2 发布于 2015 年,它允许服务器使用单个连接并行传送多个请求和响应,即 多路复用。
为了利用 HTTP/2 的多路复用,前端打包工具和框架提供了"代码分割(code split)"或"分块(chunk)"大型 CSS 文件和 JS 包的能力,并行发送较小的文件。
而底层技术则在客户端中将这些文件重新组合起来,这样网页就能正常运行。
如果未简化的压缩 CSS 文件只有 10kB,然后分成更小的块,例如 2kB,那么 CSS minify 就无关痛痒了。
05. 前端框架中的 CSS minify 和代码分割
如果你使用现代前端框架,通常会获得开箱即用的 CSS minify 或代码分割。
框架为 CSS 后处理提供了固执己见但合理的默认配置。以下是当今某些基于 JS 的现代框架处理 CSS 的方案:
05-1. Nuxt
Nuxt 附带 postcss
和许多预配置的 CSS minify 和优化插件,包括 postcss-import
、autoprefixer
和 cssnano
等。
05-2. Astro
Astro 会自动简化 CSS 并将其组合成 chunk,并进一步优化页面之间共享的 CSS 以便重用。
Astro 的另一个优化在于,它"内联"任何小于 4kB 的 CSS chunk,将 CSS 放入页面 <head>
的 <style>
标记中,防止过多迷你样式表的网络请求。这权衡了额外请求数量和页面之间可以缓存的 CSS 数量。
05-3. Next
Next 附带了许多针对使用 CSS 模块、Tailwind、Sass 和 CSS-in-JS 的预配置优化。
举个栗子,当使用 CSS 模块时,许多较小的文件将被自动打包成更少的简化 CSS 代码分割文件,从而减少网络请求的数量。
05-4. SvelteKit
SvelteKit 底层使用 Vite 来构建和打包项目,它自带可配置的 CSS 代码分割和 minify 功能。
Astro 内联所有体积小于 4kB 的 CSS 文件,而 SvelteKit 提供 inlineStyleThreshold
配置,允许你以 UTF-16 代码单元显式指定要内联的 CSS 文件的最大长度。
页面所需的且小于此阈值的所有 CSS 都会合并,并内联到 <style>
标记中。
05-5. Angular
Angular 的构建过程带有一个 --optimization
标志,它可以简化 CSS,并内联关键 CSS。
为了节省更多字节,你还可以选择在构建期间使用 removeSpecialComments
标志,删除 CSS 中的注释和其他无关字符。
高潮总结
凭借强大的压缩算法以及 HTTP/2 的广泛采用,现代前端工具通常会为我们搞定 CSS minify,尽管是以固执己见的方式。
我想,我们真的不需要再因为 CSS minify 殚精竭虑了。
参考文献
- lightning :lightningcss.dev
- Blog :blog.sentry.io/why-dont-we...
- Vite :vitejs.dev
粉丝互动
本期话题是:如何评价 CSS minify 失宠?你一般用什么前端工具处理 CSS??你可以在本文下方自由言论,文明科普。
欢迎持续关注"前端俱乐部",给前端以福利,给编程以复利。
坚持阅读的小伙伴可以给自己点赞!谢谢大家的点赞,掰掰~