script 标签的同步加载和异步加载

使用 script ​标签引入外部脚本默认是同步加载的,它会阻塞 HTML 的解析。可显式声明 async​ 和 defer​ 属性进行异步加载。

例如:

<script src="https://example.org/js/jqeruy.min.js" async>
<script src="https://example.org/js/jqeruy.min.js" defer>

async ​属性和 defer ​属性的区别:

  • async​:异步加载脚本,如果脚本下载完毕而 HTML 还未解析完成,会先停止解析而去执行脚本,执行完毕后再继续解析文档,多个 async 脚本无法保证执行的先后顺序。
  • defer​:异步下载脚本并且等待文档解析完毕后才会执行,按照 HTML 的规范,多个 defer 脚本会按照出现的先后顺序执行。

不同属性的总结

script 标签执行顺序是否阻塞解析 HTML
<script>在 HTML 中的顺序阻塞
<script async>网络请求返回顺序可能阻塞,也可能不阻塞
<script defer>在 HTML 中的顺序不阻塞

除了直接在 HTML 文件中写入 script 标签,在项目中还常常动态插入 script 标签。

那动态添加的 script​ 元素是异步还是同步加载的?

默认情况下,动态添加的 script ​元素是以异步方法加载的,相当于添加了 async ​属性。

例如:

let script = document.createElement("script");
script.src = "gibberish.js";
document.head.appendChild(script);

同时,也可以明确的设定为同步加载

例如:

let script = document.createElement("script");
script.src = "gibberish.js";
script.async = false; // 显式声明为同步加载
document.head.appendChild(script);

参见:JavaScript高级程序设计 第四版 P39

参考资源: