由于始终没有还原阻塞时的情形,无法截图。在正常情况下,是无法区别是否使用defer的区别的。后续看一下是否能模拟场景。
写demo模拟场景,由于当时的场景是外链是js加载阻塞,而不是js执行阻塞,暂时没有有效模拟。
但是可以确定的是,使用defer或async可以有效解决,外链js阻塞内部js执行的问题。

Demo详情:
clipboard.png
ndex1里面是一个耗时一秒钟的操作

clipboard.png
结果

clipboard.png
如将index1.js加上defer后

clipboard.png
clipboard.png

发现,耗时的index1,没有阻塞后续的index2和内嵌js2执行

假如将index1.js加上async

clipboard.png
clipboard.png

可发现,不但没有阻塞后续的index2和内嵌js2执行,DOMContentLoad时间也提前了

假如index1和index2都async了

clipboard.png
clipboard.png

可发现,内嵌的js1和js2,提前,外接index1,和index2顺序执行,index1阻塞了index2

假如耗时的index1 async, 后置位index2 defer

clipboard.png
clipboard.png

可发现,内嵌的js1和js2,提前, index1不阻塞了index2

假如耗时的index1 defer, 后置位index2 async

clipboard.png
clipboard.png

可发现,内嵌的js1和js2,提前, index1阻塞了index2,DOMContentLoad时间滞后

结论:

1.使用defer, async异步加载,可以使内部的js不被阻塞

2.使用defer属性的标签,永远在DOMContentLoaded事件之前执行完成。

3.defer可以阻塞async的执行,虽然两个标签都是异步下载的

回到项目中:
一站式是React渲染,React的js脚本执行一定是在DOMContentLoaded时间之前

我发现给机器人sdk加上defer之后 first paint 仍然是在DOMContentLoad之后,那我猜想,defer并不能使DOMContentLoad提前,会不会不能解决这个问题

clipboard.png

然后我找了个外网React CDN的script标签来模拟这个超时加载sdk的场景,发现首屏时间大大延长

clipboard.png
clipboard.png

延长时间基本等于js加载时间,2.63s, 而且首次渲染在DOMContentLoad之前,首屏时间没有截全,但是看看下面这个图你就明白了,肯定在2S以上,肯定是未加载的js影响了页面的渲染

clipboard.png

然后给其加上defer属性,基本影响就小很多了,😓

clipboard.png
clipboard.png

js加载时间因网络原因减少1.2s,但是DOMContentLoad少了足足2.9s, 且首次渲染仍然在DOMContentLoad之前,之后1.2s左右

解决方案:
机器人SDK(使用defer解决标题)
<script type="text/javascript" charset="utf-8" defer src="https://e.xiaojukeji.com/sdk/...;></script>
附:
魔镜SDK(使用async加载,曾经因为没有用async也阻塞过一次)
<script type="text/javascript" async charSet="utf-8" src="https://mirror-api.intra.xiao...; />
enps SDK(同步加载)
<script src="//img-ys011.didistatic.com/static/base_portal/loco.js"></script>
分享几个基础概念

defer和async的区别

defer和async可以解决script阻塞页面渲染

Defer -> 如果script标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续DOM的渲染

       defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行

clipboard.png

async的设置,会使得script脚本异步的加载并在允许的情况下执行

       async的执行,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行

情况1: HTML 还没有被解析完的时候,async脚本已经加载完了,那么 HTML 停止解析,去执行脚本,脚本执行完毕后触发DOMContentLoaded事件。如下图所示:Sdk加载阻塞页面
clipboard.png

情况2: HTML 解析完了之后,async脚本才加载完,然后再执行脚本,那么在HTML解析完毕、async脚本还没加载完的时候就触发DOMContentLoaded事件。如下图所示:Sdk加载阻

clipboard.png

html的版本 html4.0中定义了defer;html5.0中定义了async
浏览器

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 1.0 1.0 (1.7 or earlier) (Supported) (Supported) (Supported)
asyncattribute (Supported) 3.6 (1.9.2) 10 – (Supported)
deferattribute (Supported) 3.5 (1.9.1) 4 – (Supported)

DOMContentLoaded与load的区别

DOMContentLoaded:当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载

load: 当一个资源及其依赖资源已完成加载时,将触发load事件

参考文章:

再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

https://www.zhoulujun.cn/html...

浅谈script标签中的async和defer
https://www.cnblogs.com/jiasm...

高性能Javascript--脚本的无阻塞加载策略
http://www.cnblogs.com/coco1s...


kidyue
148 声望0 粉丝