为什么要避免使用 "document.write()"?


最近我们发现如果我们在页面中使用了document.wirte(),那么在 chrome 的开发者控制台会出现下面的警告信息

(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.

为啥要做这个提示呢,对于在2G,3G 或者是慢 wifi 环境下面,使用document.write()动态加载资源会让页面的展现慢10秒以上,浏览器可以呈现页面之前,必须通过解析HTML标记来构建DOM树。每当解析器遇到脚本时,它必须停止并执行它,然后才能继续解析HTML。如果脚本动态地注入另一个脚本,解析器将被迫等待更长时间才能下载资源,这可能会导致一个或多个网络往返并延迟首次渲染页面的时间,导致页面无法加载或花费的时间长于用户放弃。根据Chrome中的设备,我们了解到,通过第三方脚本插入的document.write()页面的速度通常比2G的其他页面载入速度慢两倍。

去除document.write的效果



chrome 开发者收集了28天chrome浏览器使用者的2G浏览数据,从中发现7.6%的2G加载页面中都包含了通过document.write()写入页面的跨网站,并且会中断浏览器解析的脚本。通过把这些加载脚本进行拦截加载,我们看到了以下的改进:

页面加载到达first contentful paint(视觉上让用户感觉正在加载的状态)t的状态的数量增加10%,达到完全解析状态的页面数量增加25%,减少10%由于需要刷新页面带来的用户失望
到达first contentful paint的时间减少了21%(加快速度大于1秒)
解析页面所需的时间减少了38%,差不多加快了6秒,大大减少了向用户展示内容的时间

chrome 浏览器对于document.write的策略

针对以上的测试数据,chrome 从 55版本开始,chrome 浏览器对用户使用的document.write()进行干预,如果符合以下所有的情况,页面<script>标签中的document.write()将不会被执行:

用户处于缓慢的连接状态,特别是用户在2G时。(将来可能会延伸到慢速连接的其他用户,例如慢速3G或慢速WiFi。)
document.write()在一个顶级的文件中,不适用于iframe中的document.write脚本,因为它们不会阻止主页面的呈现。
3.document.write()中加载的脚本是会阻断解析的,如果脚本中有async或者是defer属性,那么它们还是会被解析执行

4.document.write()中加载的脚本和页面地址不是同个主域的,换句话说,chrome 浏览器不会阻止script标签符合eTLD+1规则的加载(比如页面地址是www.a.com,script的地址是 js.a.com)
5.document.write()中加载的脚本尚未在浏览器HTTP缓存中。缓存中的脚本不会导致网络延迟,并且仍然会执行。''