html页面加载快慢取决于浏览器“先看到什么、先画什么、先让用户感知到什么”:结构优先级决定渲染顺序,首屏内容可读性、无跳动、不卡顿直接决定视觉感知速度。

HTML 页面加载快不快,不取决于总资源大小,而取决于浏览器“先看到什么、先画什么、先让用户感知到什么”——结构优先级决定渲染顺序,视觉感知速度由首屏内容是否可读、是否跳动、是否卡顿直接决定。
为什么把 <script></script> 放 底部还不够
很多人以为只要把 <script src="app.js"></script> 拖到 前就安全了,其实不然。浏览器仍会同步下载并执行它,一旦 JS 里有长任务(比如解析大 JSON、操作大量 DOM),首屏绘制就会卡住,用户看到白屏或闪烁。
- 真正要解决的是“阻塞解析”和“阻塞执行”两个问题:没加
defer或async的外部脚本,无论放哪都会暂停 HTML 解析 -
defer适合依赖 DOM 顺序的逻辑(如初始化组件),它等 HTML 解析完再执行,且保证顺序 -
async适合完全独立的脚本(如埋点、广告),下载不阻塞,但执行时机不可控,可能在 DOM 尚未就绪时触发 - 内联脚本(
<script>console.log('hi')</script>)永远阻塞,除非你用setTimeout或requestIdleCallback主动让出主线程
loading="lazy" 不是万能开关,首屏图片必须显式排除
给所有 <img> 加 loading="lazy" 是常见错误。浏览器对首屏图片启用懒加载,会导致最大内容绘制(LCP)延迟,甚至被搜索引擎降权。
- 首屏图片(即 viewport 内立即可见的)必须用
loading="eager"或干脆不写该属性 - 非首屏图片才加
loading="lazy",但必须同时声明width和height,否则布局会跳动(CLS 扣分) -
<iframe></iframe>也支持loading="lazy",但 Safari 15.4 之前不支持,旧环境需 fallback 到data-src+ IntersectionObserver - 注意:CSS 背景图、JS 动态插入的图片不受该属性控制,它们得靠 JS 逻辑或
preload协同处理
rel="preload" 和 rel="prefetch" 混用会拖慢首屏
这两个标签看起来相似,作用却相反:preload 是“现在就要”,prefetch 是“以后可能要”。混用或误配,会让浏览器把带宽浪费在错的地方。
-
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>必须带as和crossorigin,否则字体可能加载失败或被 CORS 拒绝 -
preload只用于当前导航中明确需要的资源(如首屏字体、关键 CSS、hero 图),DevTools Network 面板里它的 Priority 显示为high -
prefetch适合下一页才用的资源(如详情页的评论模块comments.js),Priority 是low,空闲时才下载 - 别对非关键 JS 文件做
preload,它不会推迟执行,反而抢占 HTTP/2 流,挤占真正关键资源的带宽
CSS @import 是隐藏的首屏杀手
看似只是“引入另一个文件”,@import 实际上强制串行加载,比 <link> 多一次网络往返和一次解析等待,极易拖慢 CSSOM 构建。
- 主 CSS 文件里写
@import "reset.css",浏览器必须先下载并解析完主文件,再发起 reset.css 请求,无法并行 - 媒体查询中嵌套
@import(如@media (min-width: 768px) { @import "desktop.css"; })更危险:即使用户在手机上访问,也要先下载 desktop.css - 构建工具(如 PostCSS)可自动展开
@import,但要注意路径重写和 source map 断点失效问题 - 条件化加载(如暗色主题)优先用
<link media="(prefers-color-scheme: dark)">,而不是靠 JS 或@import
最常被忽略的其实是“结构语义”本身:一个没用 <main></main>、<article></article> 的页面,即使资源全优化了,辅助技术与搜索引擎仍难以准确识别首屏关键内容;而一个 width/height 缺失的懒加载图片,哪怕只差几个像素,也会让 CLS 分数瞬间破表。优化不是加一堆属性,而是让每个标记都承担明确的渲染责任。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











