导读

本文主要总结了一些异步加载javascript脚本的方法和优缺点。

1. defer属性

<script> 标签上的defer属性允许脚本在文档解析后加载,但在DOMContentLoad事件触发前执行,且仅适用于外部脚本。

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

2. async属性

defer类似,加载时不会阻塞HTML文档的解析,但是其在加载后立即执行,不会等到整个文档解析完成后才加载,导致其执行顺序是不确定的。

1
<script async src="path/to/your-script.js>

3.动态创建script标签

通过JS创建标签并插入到文档中

1
2
3
var script = document.createElement('div')
script.src = "path/to/your-script.js";
document.body.appendChild(script);

4.使用动态加载库

requireJS

systemjs

5. IntersectionObserver

通过这个Observer,预先占位符的方式,空白div的dataset属性定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html>
<head>
<title>Lazy Load Scripts with IntersectionObserver</title>
</head>
<body>
<!-- 页面其他内容 -->
<div style="height: 150vh;">滚动下方区域加载脚本...</div>

<!-- 延迟加载脚本的占位元素 -->
<div class="lazy-script" data-src="path/to/your-script.js"></div>
<div class="lazy-script" data-src="path/to/another-script.js"></div>

<script>
// 1. 定义延迟加载函数
function lazyLoadScript(placeholder, callback) {
const src = placeholder.dataset.src;
const script = document.createElement('script');
script.src = src;
script.onload = () => {
// 脚本加载完成后停止观察并执行回调
observer.unobserve(placeholder);
callback && callback();
};
document.body.appendChild(script);
}

// 2. 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 当占位元素进入视口时加载脚本
lazyLoadScript(entry.target, () => {
console.log('脚本已加载:', entry.target.dataset.src);
});
}
});
}, {
rootMargin: '0px', // 视口边界扩展
threshold: 0.1 // 元素可见 10% 时触发
});

// 3. 查找所有占位元素并开始观察
document.querySelectorAll('.lazy-script').forEach(el => {
observer.observe(el);
});
</script>
</body>
</html>

这个方法用来图片懒加载也是同理的。

适用场景:无关核心的功能的三方脚本:广告接入、用户按需使用的功能,长页面内容等。