揭开神秘面纱:script 标签上的 defer 和 async 属性
2023-09-01 04:10:46
在现代网络开发中,我们常常面临如何优化网站性能的挑战。其中,巧妙利用 script 标签上的 defer 和 async 属性是实现此目标的有效方法。
我们经常使用 script 标签向页面插入一个常规的 JavaScript 文件:
<script src="script.js"></script>
当浏览器看到普通脚本标签声明时,它将执行以下步骤:
- 暂停文档解析器
- 创建新请求以下载脚本
- 在脚本完全下载后立即执行脚本
这样会造成页面渲染延迟,尤其是在网络连接速度较慢或脚本文件较大的情况下。为了解决这个问题,defer 和 async 属性应运而生。
defer 属性
defer 属性告诉浏览器在解析完整个 HTML 文档后才执行脚本。这确保了 HTML 结构正确加载,并防止脚本与文档元素竞争资源。
<script defer src="script.js"></script>
使用 defer 属性可以提升页面渲染速度,因为浏览器可以并行加载 HTML 和脚本文件,而无需等待脚本执行完毕。
async 属性
async 属性与 defer 属性类似,但它允许脚本在 HTML 解析过程中执行。也就是说,当浏览器遇到 script 标签时,它会立即下载脚本文件,并在下载完成后立即执行,而无需等待 HTML 文档解析完毕。
<script async src="script.js"></script>
使用 async 属性可以进一步提升页面加载速度,因为脚本可以与 HTML 并行执行。然而,需要注意的是,由于脚本执行的顺序是无法保证的,因此 async 属性可能会导致脚本依赖关系混乱,特别是当脚本之间存在依赖关系时。
那么,何时使用 defer 和 async?
一般来说,对于不依赖 HTML 结构的脚本,可以使用 async 属性,因为它可以加快脚本执行速度。对于依赖 HTML 结构的脚本,应使用 defer 属性,因为它可以确保脚本在正确的时间执行。
此外,defer 和 async 属性都可以与 type="module" 属性结合使用,以加载 ES 模块脚本。
示例代码
以下是一个使用 defer 和 async 属性加载脚本的示例:
<!-- 依赖 HTML 结构的脚本 -->
<script defer src="script1.js"></script>
<!-- 不依赖 HTML 结构的脚本 -->
<script async src="script2.js"></script>
<!-- ES 模块脚本 -->
<script type="module" defer src="script3.js"></script>
通过合理使用 defer 和 async 属性,我们可以优化网站加载速度,提升用户体验。