首屏能渲染出来的HTML块所依赖的关键CSS和JS必须在DOMContentLoaded前完成加载与解析;内联关键CSS需置于外部link之前且gzip后≤14KB,preload字体须配font-display:swap,首屏JS宜动态导入并确保DOM挂载后执行。
首屏能渲染出来的 HTML 块,其依赖的 CSS 和 JS 必须在 DOMContentLoaded 触发前完成加载与解析。不是“所有资源”,而是“首屏 DOM 渲染链上的关键路径资源”——比如 hero.jpg 的 <img> 标签若没配 loading="eager" 或没被 <link rel="preload"> 提前捞,浏览器可能等它下载完才 paint;而 main.css 若含 @import 或体积超 14KB,会直接卡住 DOM 构建。
<style>)必须放在所有外部 <link rel="stylesheet"> 之前,且 gzip 后 ≤14KB<link rel="preload" as="font"> 必须搭配 CSS 中的 font-display: swap,否则预加载反而加剧 FOITimport('./carousel.js') 动态加载,并确保调用时机在对应 DOM 节点挂载后(比如用 IntersectionObserver 监听容器可见性)defer 和 async 的执行边界在哪很多人以为把 <script> 放到 </body> 前就安全了,其实不加 defer 或 async 的外部脚本,哪怕位置再靠后,下载阶段仍会阻塞 HTML 解析——尤其在弱网下,一个未标记的 analytics.js 可能让 <main> 内容延迟 600ms 才开始解析。
defer:下载异步,执行严格按书写顺序,在 DOMContentLoaded 前、document.readyState === 'interactive' 阶段执行async:下载异步,执行不保证顺序,且可能早于 DOM 构建完成(适合无依赖的统计脚本)<script>console.log('hi')</script>)永远阻塞解析,除非包裹在 DOMContentLoaded 或 requestIdleCallback 中loading="lazy" 不能替代资源调度逻辑loading="lazy" 只是告诉浏览器“这个 <img> 或 <iframe> 不急着加载”,但它不解决 HTML 解析被阻塞的问题。如果首屏有个 <script src="heavy-bundle.js"> 没加 defer,哪怕后面所有图片都 lazy,页面照样白屏到那个 JS 下载完。
loading="lazy" 对 <img> 和 <iframe> 有效,对 <script> 和 <link rel="stylesheet"> 无效断点打在 document.getElementById('submit-btn').addEventListener() 上却没触发?90% 是 HTML 里压根没生成这个 ID 的节点,或者生成时机晚于 JS 执行——比如用 Vue 渲染的按钮,JS 在 <head> 里执行时 DOM 还是空的。
立即学习“前端免费学习笔记(深入)”;
<!--<div id="x">--> 会让整个块消失)document.querySelector('#submit-btn'),返回 null 就说明 HTML 结构或挂载时机有问题defer 加在脚本上,却忘了 main.css 里还藏着三行 @import。