若是你在控制台看到了如下信息,那么这篇文章对你而言应该会有帮助:javascript
(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.
对于如今的web的开发者而言,document.write
应该是入门级的DOM API,但实际项目开发中,却不多使用。若是面试官问你为何不去使用它,你会怎么回答?java
不少人可能会说这个性能低,那么为何低呢?先看个例子:web
document.write('<script src="https://paul.kinlan.me/ad-inject.js"></script>');
在浏览器渲染页面以前,会去根据HTML标签解析DOM树。若是解析器遇到了 <script>
标签,则会中止DOM的解析,优先执行脚本。若是这个脚本动态插入了另外一个脚本,则解析器会等待另外一个脚本下载完成到执行完成,延后了页面渲染的时间。面试
对于网络环境差的,好比 2G
的用户,经过 document.write
写入的新的脚本,可能会致使页面渲染的时间延后数十秒,用户可能就所以放弃了继续等待。基于Chrome的数据报告显示,那些经过 document.write
插入第三方脚本的页面在2G网络下比通常页面慢2倍。chrome
Chrome从55版本开始就开始选择性的干预这类写法,当同时知足如下条件的时候,会禁止脚本执行:浏览器
document.write
位于最高层级的document上(若是位于iframe中,由于不会阻止主页面渲染,因此不会干预)document.write
中的脚本是解析阻塞型的(若是带了 async
或者 defer
属性,则不会干预)通常第三方库会用这种写法来加载脚本,不过庆幸的是,大部分第三方库都支持async加载,这样就不会阻塞剩余内容的展示了。缓存
禁用 document.write
插入新的脚本便可,没有比这更好的方案,若是必须使用,则加上 async
属性。服务器
有6条之多的规则须要检查,对你来讲可能太过复杂,有没有更好的方法去检测?网络
想要知道多少用户受影响,只须要看看多少用户是2G网络,能够使用 Network Information API 来检测,而后将检测结果发到统计系统或者RUM收集系统:异步
if(navigator.connection && navigator.connection.type === 'cellular' && navigator.connection.downlinkMax <= 0.115) { // Notify your service to indicate that you might be affected by this restriction. }
若是在使用 document.write
的时候,只知足了2-5的条件,你会看到下面这种提示:
在开发者工具中看到这个你能够马上发现问题,但怎么去检测这个影响范围有多广呢?你能够检测发往你服务器请求的HTTP Headers
你可能会尝试着模拟2G网络来强制干预,但其实不必,能够直接开启这项功能,使用 chrome://flags/#disallow-doc-written-script-loads
若是经过 document.write
的方式插入的脚本被阻止了,浏览器会携带这样的请求头去请求资源:
Intervention: <https://shorturl/relevant/spec>;
若是只是warning,会携带如下请求头:
Intervention: <https://shorturl/relevant/spec>; level="warning"
这些请求头会携带在对资源的GET请求中(在实际干预的状况下异步请求)
对于现代开发者而言是幸运的,由于大部分第三方库的编写者已经再也不使用 document.write
的方式插入脚本了,项目开发中咱们只要稍微留个心就好,一些远古的第三方库可能还会存在这样的问题。