【js篇】JavaScript 脚本延迟加载的 5 种方式详解

338 阅读3分钟

在网页开发中,JavaScript 的加载和执行方式直接影响页面性能。默认情况下,浏览器在解析 HTML 页面时遇到 <script> 标签会暂停页面渲染,直到脚本加载并执行完毕。这会显著影响页面加载速度,尤其是在加载大型 JS 文件时。

为了解决这个问题,JavaScript 提供了多种延迟加载(Lazy Loading)的方式,以优化页面性能。


✅ 一句话总结

JavaScript 延迟加载的核心目的是避免阻塞页面渲染,提升首屏加载速度。常见的方法包括 deferasync、动态创建 scriptsetTimeout 和将脚本放在页面底部。


✅ 一、延迟加载的 5 种方式详解

🔹 1. defer 属性

<script src="script.js" defer></script>
  • ✅ 特点:
    • 脚本在HTML 文档解析完成后再执行;
    • 不会阻塞 HTML 解析
    • 多个带有 defer 的脚本按顺序执行
  • 📌 适用场景:
    • 脚本依赖页面 DOM;
    • 需要多个脚本顺序执行;
  • ⚠️ 注意:
    • 不适用于内联脚本(某些浏览器可能支持);

🔹 2. async 属性

<script src="script.js" async></script>
  • ✅ 特点:
    • 脚本异步加载,不阻塞 HTML 解析;
    • 一旦脚本加载完成,立即执行
    • 多个 async 脚本执行顺序不确定
  • 📌 适用场景:
    • 脚本不依赖页面 DOM
    • 脚本之间没有依赖关系
  • ⚠️ 注意:
    • 适合独立的脚本,如统计脚本、广告脚本;

🔹 3. 动态创建 DOM 脚本标签(推荐)

window.addEventListener('load', function () {
  const script = document.createElement('script');
  script.src = 'script.js';
  document.body.appendChild(script);
});
  • ✅ 特点:
    • 完全控制脚本加载时机;
    • 可监听 loaderror 等事件;
    • 脚本加载完成后自动执行
  • 📌 适用场景:
    • 需要在特定事件(如滚动、点击)后加载脚本;
    • 实现按需加载或懒加载;
  • ⚠️ 注意:
    • 不会阻塞页面渲染;
    • 更加灵活,但需要手动管理加载逻辑;

🔹 4. 使用 setTimeout 延迟加载

setTimeout(() => {
  const script = document.createElement('script');
  script.src = 'script.js';
  document.body.appendChild(script);
}, 3000); // 3秒后加载
  • ✅ 特点:
    • 通过定时器控制脚本加载时间;
    • 可以延迟到页面渲染完成后再加载;
  • 📌 适用场景:
    • 需要延迟非关键脚本
    • 控制加载节奏;
  • ⚠️ 注意:
    • 可能造成用户体验延迟;
    • 不推荐用于关键功能脚本;

🔹 5. 将脚本放在文档底部(最基础方式)

<body>
  <!-- 页面内容 -->
  <script src="script.js"></script>
</body>
  • ✅ 特点:
    • 脚本在 HTML 文档解析完成后才加载;
    • 不会阻塞页面渲染;
  • 📌 适用场景:
    • 简单项目或不支持现代加载方式的浏览器;
  • ⚠️ 注意:
    • 不如 deferasync 灵活;
    • 无法控制加载顺序或异步行为;

✅ 二、五种方式对比表格

方式是否阻塞 HTML 解析是否异步加载是否等待文档解析完成是否顺序执行适用场景
defer依赖 DOM、需顺序执行
async独立脚本、不依赖 DOM
动态创建 script是(可控制)是(按添加顺序)按需加载、高级控制
setTimeout是(可控制)是(按添加顺序)延迟加载、非关键功能
放在 body 底部简单项目、兼容性需求

✅ 三、一句话总结

使用 deferasync 是最简单、标准的延迟加载方式;动态创建 script 标签提供了更高的灵活性;而 setTimeout 和底部加载适用于简单或兼容性场景。根据脚本依赖关系和加载时机选择合适的策略,是优化页面性能的关键。


💡 进阶建议

  • 使用 defer 保证多个脚本顺序执行;
  • 使用 async 加载非关键脚本;
  • 使用动态加载实现按需加载(如滚动加载、点击加载);
  • 使用 onload 事件确保脚本加载完成后再执行相关操作;
  • 在 Vue、React 等框架中,使用动态导入(import())实现代码分割和懒加载;