异步加载和延迟加载

194 阅读3分钟

异步加载和延迟加载

在前端开发中,异步加载(Asynchronous Loading)延迟加载(Deferred Loading/Lazy Loading) 是两种提升页面性能和用户体验的关键技术。它们都旨在优化资源加载策略,但实现方式和应用场景有所不同。以下是详细解析:

一、异步加载(Asynchronous Loading)

1. 定义

  • 异步加载 是指资源(如 JavaScript 文件)的加载过程不会阻塞页面的解析和渲染。

  • 资源加载与页面解析并行进行,加载完成后立即执行。

2. 实现方式

  • JavaScript 的 async 属性
<script src="script.js" async></script>
  • 行为:脚本异步加载,下载完成后立即执行(可能中断 HTML 解析)。

    • 适用场景:独立脚本(如统计代码、广告脚本),不依赖其他脚本或 DOM。

3. 特点

  • 不阻塞渲染:HTML 解析和脚本下载并行。

  • 无序执行:多个 async 脚本的执行顺序无法保证。

  • 适用性:适合无需等待 DOM 或其他脚本的代码。

二、延迟加载(Deferred Loading)

1. 定义

  • 延迟加载 是指将资源的加载和执行推迟到合适的时机(如页面解析完成或用户触发某些操作)。

  • 分为两种类型:

    • JavaScript 的 defer 属性:延迟脚本执行。

    • 资源懒加载(Lazy Loading):延迟加载非关键资源(如图片、视频)。

2. JavaScript 的 defer 属性

<script src="script.js" defer></script>
  • 行为:脚本异步下载,但执行会延迟到 HTML 解析完成后(DOMContentLoaded 事件前)。

  • 特点

    • 保持脚本执行顺序(按文档中的顺序)。

    • 适用于依赖 DOM 或其他脚本的代码(如页面初始化逻辑)。

3. 资源懒加载(Lazy Loading)

  • 定义:延迟加载非关键资源(如图片、视频),直到它们进入视口(Viewport)或即将被用户看到时再加载。

  • 实现方式

    • HTML loading="lazy" 属性(现代浏览器支持):
<img src="placeholder.jpg" data-src="image.jpg" loading="lazy" alt="Lazy Image">
  • Intersection Observer API(编程式控制):
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img);
    }
  });
});
images.forEach(img => observer.observe(img));
  • 第三方库:如 lozad.js

  • 适用场景

    • 长页面中的图片或视频。

    • 首屏外的内容(如用户滚动后加载)。

三、对比:异步加载 vs 延迟加载

特性异步加载(async)延迟加载(defer/Lazy Loading)
资源类型主要用于 JavaScriptJavaScript、图片、视频等资源
执行时机下载完成后立即执行defer:HTML 解析后执行;懒加载:资源进入视口后加载
阻塞渲染不阻塞 HTML 解析,但执行可能阻塞defer:不阻塞;懒加载:完全不阻塞
执行顺序无序defer:有序;懒加载:按需加载
适用场景独立脚本(如统计代码)依赖 DOM 的脚本、非关键资源

四、最佳实践

1. JavaScript 加载策略

  • 关键脚本:使用 defer,确保在 DOM 就绪后按顺序执行。

  • 非关键脚本:使用 async 或动态加载(document.createElement('script'))。

  • 避免无属性的 <script>:同步加载会阻塞渲染。

2. 资源懒加载

  • 图片/视频:优先使用 loading="lazy",兼容性不足时回退到 Intersection Observer。

  • 占位符:使用低质量占位图(LQIP)或骨架屏提升用户体验。

  • 预加载关键资源:使用 <link rel="preload"> 提前加载首屏内容。

3. 性能监控

  • 使用 LighthouseWebPageTest 检测资源加载问题。

  • 通过 Chrome DevToolsNetwork 面板分析加载时序。

五、示例代码

1. 异步加载 JavaScript

<!-- 异步加载独立脚本 -->
<script src="analytics.js" async></script>

2. 延迟加载 JavaScript

<!-- 延迟执行,保持顺序 -->
<script src="vendor.js" defer></script>
<script src="app.js" defer></script>

3. 图片懒加载

<!-- 使用 loading="lazy" -->
<img src="placeholder.jpg" data-src="image.jpg" loading="lazy" alt="Lazy Image">

<!-- 使用 Intersection Observer -->
<script>
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        observer.unobserve(img);
      }
    });
  });
  document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
</script>

总结

  • 异步加载:通过 async 属性实现脚本并行加载和无序执行,适合独立脚本。

  • 延迟加载

    • defer:脚本延迟到 HTML 解析后执行,保持顺序。

    • 懒加载:延迟非关键资源(如图片)的加载,提升首屏性能。

合理结合这两种技术,可以显著优化页面加载速度、减少资源浪费,并提升用户体验。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github