HTTP/2下合并CSS未必必要,关键在首屏必用且变更频率一致的样式;需用构建工具处理依赖、顺序与隐性问题,并优先保障首屏性能。

合并 CSS 文件前先判断是否真有必要
HTTP/2 多路复用下,10 个 2KB 的 CSS 文件未必比 1 个 20KB 文件慢;但若还在 HTTP/1.1 环境,或服务端 TLS 握手慢、CDN 缓存粒度粗、磁盘 I/O 高,合并就仍有效。关键不是“文件多不多”,而是“哪些样式在首屏必用、且变更频率一致”。比如 reset.css 和 button.css 几乎每页都用、半年才改一次,适合合并;而 admin/dashboard.css 或 ab-test-v2.css 只在特定路径或实验中加载,合并反而浪费带宽。
用构建工具合并比手动拼接更可靠
手动复制粘贴容易漏掉 @import 路径重写、相对 URL 解析错误、Source Map 断链,还无法处理 CSS 变量作用域和优先级冲突。推荐交由构建工具控制依赖顺序和输出粒度:
- Webpack:用
MiniCssExtractPlugin提取 CSS,配合optimization.splitChunks把node_modules中的样式抽成vendor.css,业务样式合为app.css - Vite:默认已合并,如需自定义分组,可在
vite.config.ts中配置build.rollupOptions.output.manualChunks,例如把antd相关样式单独 chunk - PostCSS:用
postcss-import内联@import,再经cssnano压缩,适合轻量项目或 CI 构建阶段
合并后必须处理的三个隐性问题
合并本身只是第一步,后续维护常因忽略以下三点翻车:
-
@import不能替代构建时合并——它在 CSS 解析阶段触发新请求,强制串行,且无法被 Webpack/Vite 等工具静态分析 - 选择器权重冲突:多个文件里都有
.btn,合并后谁在前谁生效;必须靠构建工具保证import顺序稳定,而非靠文件名排序 - 缓存失效放大:把
dark-theme.css和reset.css合并进app.css,用户切主题就得重下整个样式包;应分离高变更率样式,用 JS 动态加载或media属性声明式引入
首屏性能比请求数更重要
盲目合并常导致首屏变慢:一个 150KB 的 app.css 会阻塞渲染直到全部下载解析完成,哪怕其中 120KB 是滚动到底部才用的 product-list.css 和 modal.css。更优做法是:
立即学习“前端免费学习笔记(深入)”;
- 提取首屏关键 CSS(如 header、hero section),内联到
<head>中 - 非关键 CSS 用
<link rel="preload" as="style" onload="this.rel='stylesheet'">异步加载 - 打印样式、无障碍偏好等用
media="print"或media="(prefers-reduced-motion)"声明,浏览器不阻塞主渲染流程
真正难的不是“怎么合并”,而是判断哪些样式该一起打包、哪些该拆开、哪些该延迟——这需要结合路由结构、用户行为数据和缓存策略来定,而不是套用“合并越多越好”的经验。


















