本文是技術圈 google 瀏覽器前端新特性播報的推送,歡迎你們加入html
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的其餘頁面載入速度慢兩倍。chrome
document.write
的效果chrome 開發者收集了28天chrome瀏覽器使用者的2G瀏覽數據,從中發現7.6%的2G加載頁面中都包含了經過document.write()
寫入頁面的跨網站,而且會中斷瀏覽器解析的腳本。經過把這些加載腳本進行攔截加載,咱們看到了如下的改進:segmentfault
first contentful paint(視覺上讓用戶感受正在加載的狀態)t
的狀態的數量增長10%,達到徹底解析狀態的頁面數量增長25%,減小10%因爲須要刷新頁面帶來的用戶失望first contentful paint
的時間減小了21%(加快速度大於1秒)document.write
的策略針對以上的測試數據,chrome 從 55版本開始,chrome 瀏覽器對用戶使用的document.write()
進行干預,若是符合如下全部的狀況,頁面<script>
標籤中的document.write()
將不會被執行:api
document.write()
在一個頂級的文件中,不適用於iframe中的document.write腳本,由於它們不會阻止主頁面的呈現。document.write()
中加載的腳本是會阻斷解析的,若是腳本中有async
或者是defer
屬性,那麼它們仍是會被解析執行4.document.write()
中加載的腳本和頁面地址不是同個主域的,換句話說,chrome 瀏覽器不會阻止script
標籤符合eTLD+1
規則的加載(好比頁面地址是www.a.com
,script
的地址是 js.a.com
)
5.document.write()
中加載的腳本還沒有在瀏覽器HTTP緩存中。緩存中的腳本不會致使網絡延遲,而且仍然會執行。瀏覽器
document.write
是否被執行限制了chrome 提供了多種方式來檢測你的document.write
請求是否被限制了緩存
因爲上面的規則現階段只針對慢速狀況2G,所以首先能夠先分析出來,你的網站的2G 用戶佔比,經過chrome
提供的網絡信息 API,能夠判斷用戶是否是在2G 環境下面,代碼以下網絡
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. }
在chrome devtools
中,若是頁面知足上面的2-5的規則,則會在chrome devtools
中看到以下警告app
異步
上面兩種方式結合以後能夠對影響的用戶量有一個初步的判斷,若是要作精確的判斷,能夠檢查 HTTP 頭部:
當插入的腳本document.write被阻止時,Chrome會將如下標頭髮送到所請求的資源:
Intervention: <https://shorturl/relevant/spec>;
當document.write發現插入腳本時,可能會在不一樣狀況下被阻止,Chrome可能會發送:
Intervention: <https://shorturl/relevant/spec>; level="warning"
干預頭將做爲腳本的GET請求的一部分發送(在實際干預的狀況下異步)。
因爲document.write
會減慢頁面的加載,能夠考慮使用appendChild
等 api 將元素插入頁面中,不過這二者有如下的區別
document.write
的參數是一個 html 字符串,appendChild
是一個Node
對象document.write
寫入 script 標籤,標籤與標籤之間的加載是同步的,也就是說,標籤的加載順序會和document.write
的執行順序相同;而使用appendChild
插入多個sciprt
標籤時,標籤加載的順序是不肯定的,先加載完成的先執行,所以經過appendChild
插入script
標籤時,要注意是否須要對加載的順序進行控制,能夠經過script.onload
進行順序回調插入