常见的几种脚本的加载方式,比如:script、async、defer:
<script src='xxx'></script>
<script src='xxx' async></script>
<script src='xxx' defer></script>
相信有不少人只是听过或者通过第三方框架配置过,但并没有实际深入研究过,比如我🌝,也一定会有很多疑问:
- 它们的区别到底是啥?
- 会不会阻塞Html的解析?
- 它们各自加载的顺序谁来决定?
- 什么场景下使用哪种方式?
那带着上面这些疑问,我们继续:
script
浏览器解析HTML时,如果遇到script标签,会暂停HTML的解析发起网络请求获取JS脚本,然后让JS引擎执行JS脚本,执行完成后再恢复对HTML的解析,过程如下:
可以看到script的请求和执行阻阻塞了HTML的解析,如果网络请求迟迟得不到响应,浏览器就会出现白屏情况。
async script
当浏览器解析Html时,如果遇到async script会异步请求JS脚本时不会阻塞HTML的解析,但是请求完成后如果HTML的解析还没有完成,就会停止对html的解析执行JS脚本:
但是如果Html已经解析完成则不会出现阻塞情况。
结论:async script有可能会阻塞Html的解析,也有可能不会
比如antd官网,就有很多资源是通过async script加载的。
如果存在多个async,其执行顺序是不确定的,完全取决于请求完成的先后顺序。
defer script
defer表示延迟,即:也是异步请求获取资源,但是不会阻塞Html的解析,等Html解析完成后才会继续解析JS脚本
可以看到掘金就使用了很多defer script加载JS
如果有多个defer script,其加载顺序取决于在页面中的引入顺序。
总结
script标签 | JS执行顺序 | 是否阻塞Html的解析 |
---|---|---|
script | 取决于Html中的引入顺序 | 阻塞 |
script async | 取决于网络请求返回的顺序 | 可能阻塞也可能不阻塞 |
script defer | 取决于Html中的引入顺序 | 不阻塞 |
使用场景
那到底什么场景下该选用哪种加载方式呢?
- 如果每个外部文件不依赖执行的先后顺序,可以使用 async
- 如果一个脚本依赖另一个脚本的执行,可以使用 defer
浏览器兼容性
《重学JavaScript系列专栏》其它文章推荐:
- 发布订阅者模式原来是这样 “搞事情” 的!
- 你家3岁小孩也能看懂的防抖和节流
- 手动模拟实现call、apply和bind方法---call和apply方法实现
- 手写call、apply、bind方法---bind方法实现
《手撕源码系列专栏》文章推荐
《Webpack配置从基础到高阶系列专栏》文章推荐