Sdk加载阻塞页面渲染问题的总结

44次阅读

共计 2355 个字符,预计需要花费 6 分钟才能阅读完成。

由于始终没有还原阻塞时的情形,无法截图。在正常情况下,是无法区别是否使用 defer 的区别的。后续看一下是否能模拟场景。写 demo 模拟场景,由于当时的场景是外链是 js 加载阻塞,而不是 js 执行阻塞,暂时没有有效模拟。但是可以确定的是,使用 defer 或 async 可以有效解决,外链 js 阻塞内部 js 执行的问题。
Demo 详情:ndex1 里面是一个耗时一秒钟的操作
结果
如将 index1.js 加上 defer 后

发现,耗时的 index1,没有阻塞后续的 index2 和内嵌 js2 执行
假如将 index1.js 加上 async

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

可发现,内嵌的 js1 和 js2,提前,外接 index1, 和 index2 顺序执行,index1 阻塞了 index2
假如耗时的 index1 async, 后置位 index2 defer

可发现,内嵌的 js1 和 js2,提前, index1 不阻塞了 index2
假如耗时的 index1 defer, 后置位 index2 async

可发现,内嵌的 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 提前,会不会不能解决这个问题

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

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

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

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 事件调用前执行

async 的设置,会使得 script 脚本异步的加载并在允许的情况下执行
async 的执行,并不会按着 script 在页面中的顺序来执行,而是谁先加载完谁执行

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

html 的版本 html4.0 中定义了 defer;html5.0 中定义了 async 浏览器
Feature Chrome Firefox (Gecko) Internet Explorer Opera SafariBasic 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 和 deferhttps://www.cnblogs.com/jiasm…
高性能 Javascript– 脚本的无阻塞加载策略 http://www.cnblogs.com/coco1s…

正文完
 0