异步加载和延迟加载
在前端开发中,异步加载(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"属性(现代浏览器支持):
- HTML
<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) |
|---|---|---|
| 资源类型 | 主要用于 JavaScript | JavaScript、图片、视频等资源 |
| 执行时机 | 下载完成后立即执行 | 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. 性能监控
-
使用 Lighthouse 或 WebPageTest 检测资源加载问题。
-
通过 Chrome DevTools 的
Network面板分析加载时序。
五、示例代码
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