在我上篇文章裏,我提到一種使用iframe完成無阻塞腳本加載的方式,由於我對iframe的偏見很大,因此上篇文章裏我沒有展開討論這個問題。javascript
文章發表後有位網友問了我這樣一個問題,下面是他問題的原文,以下所示:css
我一個電商後臺系統,用的表格控件是flexigrid,,裏面是個iframe來的,每個tab就是一個iframe,如今遇到的問題就是,若是其中一個或者多個iframe在加載數據,還沒加載完,若是這個時候,我再去開一個tab,也是查找數據,可能數據量很大,或者提交數據(其餘的iframe可能還在加載數據),這個時候很容易出現瀏覽器卡死,一直轉圈的現象,這個跟你說的這個js阻塞也有關係吧。跟這個js單線程的特性,線程阻塞有多大的關係~~
這個現象頗有趣,就和我在上篇文章裏談到我思考無阻塞腳本加載的源起同樣,研究這個朋友提供的現象應該也能給咱們很大的收穫。html
首先,這位朋友提到「若是其中一個或者多個iframe在加載數據,還沒加載完,若是這個時候,我再去開一個tab,也是查找數據,可能數據量很大,或者提交數據(其餘的iframe可能還在加載數據),這個時候很容易出現瀏覽器卡死,一直轉圈的現象」,這個現象讓我有個疑問:前端
首先咱們要明確頁面使用iframe時候等於一個頁面裏嵌套一個頁面,iframe的src指向的頁面其實和父頁面是相對獨立的,那麼一個帶了iframe的頁面,父頁面的加載過程和iframe加載的過程是怎樣的關係了,具體點就是父頁面是否是要等待iframe頁面裏全部資源加載完畢後纔會觸發onload事件,頁面的onload事件觸發了,也就表明頁面的忙指示結束,而忙指示是咱們衡量頁面是否被阻塞的一個重要標誌。java
幸運的是有人已經幫咱們作了這個實驗,下面我來描述下這個實驗的方式:web
阻塞加載方式即在頁面直接寫:chrome
<iframe src=」url」></iframe>
Iframe的url指向的頁面分爲四種類型:apache
1.url指向一個空文檔,空文檔不是指頁面指向的網頁不存在,而是指向網頁裏只有最基本的html,例如:跨域
<html><head></head><body><p>ddddd</p></body></html>
這時候iframe加載就不會由於內部靜態資源而被阻塞。瀏覽器
2.url指向的頁面裏包含圖片;
3.url指向的頁面包含外部腳本;
4.url指向的頁面包含外部css樣式文件。
上面的靜態資源,實驗設計者都讓它們的加載有延時,實驗的結果是使人失望的,這些靜態資源加載都會阻塞父頁面的加載,即iframe的加載延長了忙指示結束的時間。
接下來實驗者又作了一個實驗,這個時候在父頁面裏iframe的src設爲空,而後使用javascript代碼給iframe設定src的值,賦值的時機也是在onload事件以前,而url指向和上個實驗一致,結果是在以webkit爲內核的safari和chrome下,頁面加載明顯變快,iframe的加載沒有阻塞父頁面的加載,可是在其餘瀏覽器下這個結果是使人失望的,阻塞任然存在,甚至比之前還要嚴重。
Iframe的加載是能阻塞父頁面的加載,上面朋友的現象描述裏:一個iframe沒有加載完畢,用戶可能就會選擇另一個iframe,另外一個iframe也在加載新頁面,這個描述說明了,這個朋友的iframe的src應該都是使用javascript設置,而不是事先填好的,他的場景符合實驗二的狀況。這裏又會產生一個問題,第一個iframe多是和主頁面資源加載同步的,即主頁面頗有可能還沒觸發onload事件,爲啥用戶還能觸發iframe的加載操做,按我原來的邏輯,這時候頁面應該是不能接收任何響應的,這裏我要糾正下這個觀點,頁面被阻塞不表明頁面會中止接收用戶的所作的相關操做,例如在ie瀏覽器,若是頁面被阻塞,用戶點擊了兩次按鈕,瀏覽器會認爲用戶的操做是有效的,會將用戶的操做加入到瀏覽器執行的UI線程裏的,這是瀏覽器對於性能不佳網頁的一個妥協作法。
Iframe阻塞頁面加載的問題還有更多深層次的緣由,首先iframe頁面dom元素中加載最慢的,你們能夠看看下面這張圖:
咱們使用dom在頁面裏建立iframe、a、div、srcipt和style節點,第一欄是建立10個節點,第二欄是建立100個節點,第三欄是建立1000個節點,數值是表明建立的時間,因而可知建立iframe越多,耗時越長,可見iframe自己就是頁面性能的瓶頸所在。
在前面文章裏我講到網站爲了提高頁面資源並行下載的,能夠將通用的靜態資源放到一個獨立的域名下,跨域能夠增長頁面鏈接數,使用iframe的頁面會有兩個url,iframe能達到增長並行下載的目的嗎?若是iframe的url和父頁面的url不一樣,能不能增長我沒有作過測試,沒法回答,可是針對這個朋友的問題,他使用的iframe的url確定會和父頁面在同一個域下面,由於他使用的iframe目的是爲了佈局而不是爲了嵌入其餘web的頁面,iframe和父頁面同域的結果就是併發鏈接數是不能被增長的,由於iframe是指向一個完整的頁面,在加上上面說的iframe其實也會阻塞頁面的加載,所以這個場景下就等於瀏覽器同時加載兩個獨立頁面卻要遵照一個頁面加載的方案,結果天然是頁面會變得更慢。
因爲這個朋友的應用是內部的控制檯,所以它的網站絕對不會有作那些提高網站性能的優化工做,網站優化裏有一條就是:將外部的css文件和js文件緩存,因此這個朋友網站確定會出現這個問題,第一個iframe還沒加載完,用戶打開了第二個iframe,這兩個iframe使用的外部css文件和js文件可能大部分相同,可是它們在每一個iframe裏都會被從新加載,並且第一個iframe沒有加載完畢,還會阻塞第二個iframe對靜態資源的加載,若是開啓的iframe越多,阻塞就越加嚴重,後果天然也是網站愈來愈慢。
那麼咱們該怎麼幫這個朋友解決他的問題了?最好的方式就是將iframe去掉,使用div來實現選項卡,這麼作太殘酷,要重構整個前端代碼,這個朋友問個人目的就是不想這麼幹了。
因此要考慮下代價較少的方法,下面是我晚上想到的,但願看了我博客的大牛們也會有更多更好的建議,我想到的以下:
文章寫畢,最後再重申一下但願有大牛看了本人的文章,能告訴咱們更多更好的方式。