当前位置: 首页 > news >正文

JavaScript延迟加载

JavaScript延迟加载的方式

JS延迟加载方式
defer属性
async属性
动态创建script标签
将脚本放在页面底部
使用模块化导入(import)
事件监听器(DOMContentLoaded)

⭐ defer属性详解

sequenceDiagramparticipant HTML解析participant 脚本下载participant 脚本执行HTML解析->>HTML解析: 开始解析HTMLHTML解析->>脚本下载: 遇到defer脚本,开始下载HTML解析->>HTML解析: 继续解析HTML(不阻塞)脚本下载->>脚本下载: 后台下载脚本HTML解析->>HTML解析: 完成HTML解析HTML解析->>脚本执行: DOM构建完成脚本执行->>脚本执行: 按顺序执行defer脚本style HTML解析 fill:#ffcc99style 脚本执行 fill:#ffcc99
<!-- defer属性使用示例 -->
<script defer src="script.js"></script>

defer特性:

  • ✅ 并行下载脚本,不阻塞HTML解析
  • ✅ 等待HTML解析完成(DOMContentLoaded事件前)执行
  • ✅ 多个defer脚本按照它们在文档中的顺序执行
  • ✅ 仅适用于外部脚本(有src属性)

🌟 各种延迟加载方式对比

1. async属性

<script async src="analytics.js"></script>
sequenceDiagramparticipant HTML解析participant 脚本下载participant 脚本执行HTML解析->>HTML解析: 开始解析HTMLHTML解析->>脚本下载: 遇到async脚本,开始下载HTML解析->>HTML解析: 继续解析HTML(不阻塞)脚本下载->>脚本下载: 后台下载脚本脚本下载->>HTML解析: 下载完成,暂停HTML解析脚本下载->>脚本执行: 立即执行脚本脚本执行->>HTML解析: 执行完成,继续HTML解析style 脚本执行 fill:#ffcc99

async特性:

  • ✅ 并行下载脚本,不阻塞HTML解析
  • ❌ 下载完成后立即执行,会中断HTML解析
  • ❌ 多个async脚本执行顺序不保证(谁先下载完谁先执行)
  • ✅ 适用于独立的脚本,不依赖DOM和其他脚本

2. 动态创建script标签

function loadScript(url, callback) {const script = document.createElement('script');script.src = url;if (callback) {script.onload = callback;}document.body.appendChild(script);
}// 使用示例
loadScript('script.js', function() {console.log('脚本加载完成');
});

动态创建特性:

  • ✅ 可以完全控制脚本加载时机
  • ✅ 可以添加回调函数处理加载完成事件
  • ✅ 默认异步加载(相当于async行为)
  • ✅ 可以通过设置async=false实现类似defer的行为

3. 将脚本放在页面底部

<!DOCTYPE html>
<html>
<head><title>页面标题</title>
</head>
<body><!-- 页面内容 --><!-- 脚本放在底部 --><script src="script.js"></script>
</body>
</html>

底部放置特性:

  • ✅ HTML解析不会被中断
  • ✅ 简单易实现
  • ❌ 脚本下载延迟到HTML解析到底部
  • ❌ 不是真正的并行下载

4. 使用模块化导入

<script type="module" src="module.js"></script>
// 动态导入
import('./module.js').then(module => {module.init();
});

模块化特性:

  • ✅ 默认具有defer行为
  • ✅ 支持按需加载(动态import)
  • ✅ 严格模式和作用域隔离
  • ❌ 浏览器兼容性要求较高

5. 使用事件监听器

document.addEventListener('DOMContentLoaded', function() {// 加载脚本const script = document.createElement('script');script.src = 'script.js';document.body.appendChild(script);
});

事件监听特性:

  • ✅ 确保DOM完全构建后加载
  • ✅ 适合需要操作DOM的脚本
  • ❌ 不是真正的并行下载
  • ❌ 代码量较多

📊 加载方式对比表

加载方式HTML解析阻塞执行时机执行顺序兼容性使用场景
defer不阻塞DOM就绪后,DOMContentLoaded前保持顺序良好依赖DOM且有依赖关系的脚本
async不阻塞下载,执行时阻塞下载完成后立即执行不保证良好独立脚本,如统计分析
动态创建通常不阻塞可控制可控制极佳按需加载,条件加载
底部放置不阻塞HTML解析后按放置顺序极佳简单项目,无特殊需求
模块化不阻塞类似defer保持顺序一般现代应用,模块化代码

🎯 如何选择正确的延迟加载方式

选择延迟加载方式
脚本是否依赖DOM?
是否依赖其他脚本?
是否是分析统计类?
使用defer
需要精确控制加载?
使用async
动态创建script
放置页面底部

📚 总结

  • defer (最推荐):

    • ⚠️ 并行下载,不阻塞HTML解析
    • ⚠️ DOM构建完成后,DOMContentLoaded前执行
    • ⚠️ 保证执行顺序
    • ⚠️ 适合依赖DOM且有依赖关系的脚本
  • async:

    • 并行下载,下载完立即执行
    • 适合独立的脚本,如统计分析
  • 动态创建script:

    • 灵活控制加载和执行时机
    • 适合条件加载和按需加载
  • 底部放置:

    • 简单有效,确保DOM已加载
    • 但下载延迟到底部
  • 模块化导入:

    • 现代化方案,具有defer特性
    • 支持按需和条件导入

相关文章:

  • 【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
  • OpenStack Yoga版安装笔记(25)Nova Cell理解
  • 【ESP32】st7735s + LVGL使用-------图片显示
  • 【五一培训】Day1
  • MySQL基础关键_003_DQL(二)
  • WEB UI自动化测试之Selenium框架学习
  • 【HarmonyOS】作业三 UI
  • 【信息系统项目管理师-论文真题】2024上半年(第二批)论文详解(包括解题思路和写作要点)
  • 【云备份】服务端工具类实现
  • Unity动态列表+UniTask异步数据请求
  • 嵌入式AI还是一片蓝海
  • MySQL 服务搭建
  • 范式演进:从ETL到ELT及未来展望
  • 多智能体空域协同中的伦理博弈与系统调停
  • 题解:CF1398D Colored Rectangles
  • 华为eNSP:多区域集成IS-IS
  • Python基本语法(控制语句)
  • Java中修饰类的关键字
  • windows中Python的pip工具换源的方法及其原理
  • RISC-V AIA SPEC学习(四)
  • 申活观察|咖香涌动北外滩,带来哪些消费新想象?
  • 【社论】法治是对民营经济最好的促进
  • 五一去哪儿|外国朋友来中国,“买买买”成为跨境旅游新趋势
  • 孙磊已任中国常驻联合国副代表、特命全权大使
  • 结婚这件事,年轻人到底怎么想的?
  • 蔡澜回应“入ICU观察”称未至于病危,助理:只是老毛病