用 提前加载自托管 CSS,不阻塞渲染,需配合 onload="this.rel='stylesheet'" 应用样式;Safari 旧版需用 addEventListener 回退;静态 CSS 应配 Cache-Control: public, max-age=31536000, immutable 并带哈希名,无哈希则禁用 immutable;禁用 @import,因其串行阻塞且不可预加载;HTTP/2 下小 CSS 内联,非关键 CSS 拆分 + preload + media 控制;immutable 必须与文件名哈希配合使用。

如何用 <link rel="preload"> 提前加载自托管 CSS
浏览器默认按 HTML 解析顺序加载 CSS,<link rel="stylesheet"> 会阻塞渲染,直到 CSSOM 构建完成。如果文件在 CDN 或本地磁盘上,网络延迟或磁盘 I/O 都可能拖慢首屏。用 <link rel="preload"> 可让浏览器在解析 HTML 早期就发起请求,不阻塞渲染,也不执行 CSS。
- 必须搭配
as="style",否则浏览器不会复用该资源到后续<link rel="stylesheet"> - 不能省略
onload回调:预加载本身不应用样式,需手动插入<link rel="stylesheet">或设置rel属性切换 - 示例写法:
<link rel="preload" href="/css/main.css" as="style" onload="this.rel='stylesheet'">
- 注意:Safari 对
onload支持较晚(iOS 15.4+ / macOS 12.3+),旧版本需 fallback 到addEventListener('load', ...)
CSS 文件的 Cache-Control 设置要点
自托管意味着你完全控制 HTTP 响应头,Cache-Control 是提速核心。设错会导致反复请求,设太激进又会让更新失效。
- 静态 CSS(带哈希名如
main.a1b2c3.css):用Cache-Control: public, max-age=31536000, immutable—— 浏览器永久缓存,无需校验 - 无哈希的 CSS(如
theme.css):避免immutable,改用max-age=3600+ETag或Last-Modified,确保更新可被感知 - Nginx 示例配置:
location ~* \.css$ {<br> add_header Cache-Control "public, max-age=31536000, immutable";<br>} - 开发环境建议禁用缓存:
Cache-Control: no-store,避免本地调试时看到旧样式
为什么不要用 @import 加载自托管 CSS
@import 在 CSS 内部使用,会触发串行请求、无法并行下载,且阻塞后续规则解析,性能比 <link> 差一个数量级。
- 即使写在
<style></style>标签里,@import url("base.css")也会等当前样式表 parse 完才发请求 - 无法被
preload或prefetch提前触发 - 部分构建工具(如 Webpack 的 MiniCssExtractPlugin)会把
@import转为<link>,但源码中仍存在隐式依赖风险 - 真实错误现象:
DevTools Network 面板显示 CSS 请求排在 JS 后、白屏时间明显延长
HTTP/2 下是否还要合并 CSS 文件?
HTTP/2 支持多路复用,单个连接并发传输多个资源,理论上不用再拼大 CSS。但现实有折中。
立即学习“前端免费学习笔记(深入)”;
- 小文件(
)仍建议内联关键 CSS(<code><style></style>),避免额外请求开销 - 非关键 CSS(如打印样式、主题切换样式)可拆分并
preload或lazy load,用media属性控制加载时机 - 注意服务器推送(HTTP/2 Push)已基本被主流浏览器弃用,别依赖它
- 真正影响缓存效率的是变更频率:高频更新的组件样式和低频的全局样式混在一个文件里,会导致用户反复下载未变部分
实际部署时,最常被忽略的是 immutable 和文件名哈希的配合 —— 缺一不可。没哈希却加 immutable,更新后用户永远看不到新样式;有哈希却不加 immutable,浏览器仍会发条件请求,白白浪费一次往返。


















