应控制link数量在3–5个以内,通过构建工具合并CSS并区分critical/non-critical样式,用media或preload实现非阻塞加载,HTTP/2下仍需优化请求粒度。
确实拖慢首屏浏览器对同一域名的并行 请求有数量限制(通常 6–8 个),且每个 CSS 文件都会触发一次 TCP 连接、DNS 查询(未复用时)和渲染阻塞。哪怕总大小不大,10 个 2KB 的文件,加载耗时可能远超 1 个 20KB 的文件。
关键不是“CSS 大”,而是“请求多 + 阻塞强”。优化方向只有两个:减少请求数、降低阻塞影响。
Webpack、Vite、Rollup 都能通过插件(如 mini-css-extract-plugin 或 css-bundle)把多个 .css 文件打包进少数几个输出文件。但要注意:
main.css —— 首屏根本用不到的规则也会强制解析和计算critical(首屏必需)和 non-critical(滚动后/交互后才需)样式。前者内联或提前加载,后者延迟或异步加载
build.rollupOptions.output.manualChunks 可按模块路径拆分,比如把 node_modules/ 单独抽成 vendor.css,避免业务 CSS 更新导致缓存失效export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'lodash-es'],
chart: ['echarts'],
}
}
}
}
})
media 和 onload 实现非阻塞加载对非首屏、非关键 CSS(如打印样式、深色主题、弹窗组件样式),可移出阻塞链:
media="print" 加载,浏览器不阻塞渲染,后续 JS 切换 media 值激活rel="preload" + onload 动态切换 rel:注意:onload 在 Safari 旧版和部分 iOS WebView 中不触发, 是降级保障;不要对 main.css 这类核心样式这么干,会引发 FOUC。
HTTP/2 支持多路复用,理论上 10 个 CSS 请求可复用一个 TCP 连接,减少了连接开销。但以下问题依然存在:

所以即使启用了 HTTP/2,也建议控制 数量在 3–5 个以内,并按功能域切分(如 base.css、layout.css、component.css),而不是回到“一个巨无霸 CSS”老路。