html defer延迟加载脚本

2026-04-23 19:00:07 2001阅读 0评论

用 defer 优雅地掌控页面脚本加载的节奏

在网页加载的“交响乐”里,脚本加载往往是一把双刃剑。如果它来得太早,会在页面渲染前抢走资源,让布局迟迟不见;如果太晚,又会让功能初始化延迟,体验打折扣。用好 HTML 的 <script> 元素与 defer 属性,能让人与机器的节奏更默契一些。

为什么 defer 重要

简单说,defer 把脚本的执行放到文档解析完成后、但在页面渲染之前进行。这意味着它不阻塞 HTML 解析,也不同于 async 的“先执行后解析”,更不如同位的内联脚本在渲染前就插入执行。

在真实场景里,比如加载一个统计模块或第三方组件,把它的加载改为 defer,通常能明显减少首次可交互时间(FOIT)与感知延迟,页面会更顺滑。

基本用法与核心差异

<script src="/path/to/script.js" defer></script>

在多个脚本并存时,浏览器会按文档中出现的顺序执行 defer 脚本;若同时出现 async 与 defer,它们会被分别处理:async 一旦下载即执行,可能中断页面渲染;defer 被统一收集,待解析完成后再按顺序执行。

实战场景:组件与统计模块

设想你在加载页面时需要初始化一个组件库与一个统计模块。把它们放到 defer 集合里,能避免阻塞解析,又能保证初始化在渲染前完成。

<!-- 主要渲染资源 -->
<div id="app"></div>
<script src="/bundle.js" defer></script>

<!-- 统计模块,按需加载 -->
<script src="/analytics.js" defer></script>

<!-- 组件库初始化 -->
<script src="/components.js" defer></script>

进阶:动态脚本与 defer

当需要动态创建脚本时,也可以使用 defer,但要注意执行顺序。

const script = document.createElement('script');
script.src = '/dynamic-script.js';
script.defer = true;
document.head.appendChild(script);

如果依赖顺序严格,可用 Promise 模拟依赖注入:

Promise.all([
  new Promise(resolve => {
    const s = document.createElement('script');
    s.src = '/depend1.js';
    s.defer = true;
    s.onload = resolve;
    document.head.appendChild(s);
  }),
  new Promise(resolve => {
    const s = document.createElement('script');
    s.src = '/depend2.js';
    s.defer = true;
    s.onload = resolve;
    document.head.appendChild(s);
  })
]).then(() => {
  console.log('依赖加载就绪,可安全初始化主脚本');
});

避坑指南:常见误解与注意点

  • 不把 defer 作为“无条件的晚执行”:某些初始化必须在渲染前完成,过晚可能导致布局抖动或交互延迟。
  • 避免在 defer 脚本中进行长时间同步操作,否则会拖慢后续脚本执行与页面渲染。
  • 对于必须在解析阶段就能运行的脚本(如定义立即使用的全局变量),尽量不要使用 defer。

结语

用好 defer,就是在页面加载与脚本执行之间找到合适的节拍。它不是万能的,但能显著减少不必要的阻塞,提升页面的首屏体验与可感知性能。在模块化与组件化日益复杂的今天,掌握这一技巧,能让你的页面更轻、更稳、更友好。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,2001人围观)

还没有评论,来说两句吧...

目录[+]