css阻塞,js阻塞
雖然感覺,這東西完全沒啥用!寫了這麼久我也沒遇到過 !但是萬一那天遇到了,回來看看相比也是極好的!
css阻塞:css預設為阻塞渲染資源(阻塞渲染資源與非阻塞渲染資源的不同之處在於下載的優先級別問題,阻塞資源高,優先下載),無論是否為css阻塞資源 都是會下載的,時間先後而已;媒介型別和媒體查詢,可以讓我們標記一些css為非阻塞資源。
js阻塞:js下載的時候瀏覽器會終止其他檔案的下載,但是新式瀏覽器都開始做 js 的並行下載 也就是說js阻塞 可以在未來的某個時間忽略了,js阻塞 會阻塞css下載,所以這也是為什麼一般強調初學者將css放在頭部 ,js放在尾部,渲染js長時間執行的函式的時候 建議使用 settimeout 將這個手動延遲 不然你的使用者可能會對著白色螢幕發呆!
網上找了點資料描繪的極為詳細:
【導讀】:在預設情況下,CSS會被當做渲染中的阻塞性資源,也就是說瀏覽器即使已經處理好了某些頁面內容,只要CSSOM沒有構建好,便不會進行渲染。所以要給你的CSS瘦身,提高傳輸速度,並使用媒介型別和媒介查詢來解除阻塞。
在前部分中我們看到了關鍵的渲染途徑需要同時具備DOM(Document Object Mode,文件物件模型)和CSSOM(CSS Object Model,CSS物件模型)來構造渲染樹,這在渲染效能上有一個很重要的含義:HTML和CSS都是渲染過程中的阻塞性資源。HTML很明顯,因為沒有DOM的話,我們也沒有任何東西來渲染,但是對CSS的要求也許並不明顯。如果我們嘗試渲染一個普通的頁面,而不讓CSS阻塞渲染過程,那會發生什麼呢?
學習重點
- 預設情況下CSS被視為一種阻塞性渲染資源
- 媒介型別和媒介查詢讓我們能把一些CSS資源標記為非阻塞性渲染資源
- 不管是阻塞性的還是非阻塞性的行為,所有的CSS資源都是通過瀏覽器下載的
有 CSS 的紐約時報網站 無 CSS 的紐約時報網站
上面的例子展示了NYTimes在使用和不使用CSS時的樣子,這表明了為什麼直到CSS可用時才渲染 — 缺少CSS的頁面實際上是無法使用的。事實上,右邊的使用者體驗通常叫做“Flash of Unstyled Content” (FOUC)。所以結果是,瀏覽器會在同時具備了DOM和CSSOM時才渲染介面。
CSS是一種阻塞性渲染資源,需要讓它儘可能快地下載到客戶端,並在第一次渲染的時候進行優化。
然而,假如一些CSS樣式只能用於某些特定的條件下怎麼辦呢?例如,當頁面被列印時,或者被投影到大螢幕時。如果這些資源能夠不阻塞渲染的話,那就太棒了!
CSS “媒介型別”和“媒介查詢”使我們能夠處理下列情況:
XHTML123 | <link href="style.css"rel="stylesheet"><link href="print.css"rel="stylesheet"media="print"><link href="other.css"rel="stylesheet"media="(min-width:40em)”> |
一個媒介查詢由一個媒介型別和0個或多個檢查特殊媒介特徵的條件的表示式構成。例如,我們的第一個樣式宣告沒有使用提供任何媒介型別和查詢,因此它適用於各種情況 — 也就是說,它總是會阻塞渲染。另一方面,第二種樣式只被用於當內容被列印時 — 也許你想要重新設定佈局或改變字型等等 — 因此當這個樣式第一次被載入時,它不會阻塞頁面的渲染。最後一個樣式宣告提供了一個由瀏覽器來執行的媒介查詢:如果條件符合的話,瀏覽器會在該樣式下載完並處理完後才渲染。
使用媒介查詢,我們的外觀可以定製成特定的使用案例,例如顯示和列印,還有一些動態的條件,例如在螢幕方向上的改變,調整大小等等。當宣告你的樣式資源時,一定要仔細注意媒介型別和媒介查詢,因為它們會對關鍵渲染路徑有很大的效能影響!
讓我們來考慮一些實際的例子:
XHTML1 2 3 4 | <linkhref="style.css"rel="stylesheet"> <linkhref="style.css"rel="stylesheet"media="screen"> <linkhref="portrait.css"rel="stylesheet"media="orientation:portrait"> <linkhref="print.css"rel="stylesheet"media=“print"> |
- 第一條宣告是阻塞渲染的,並且匹配所有情況。
- 第二條宣告也是阻塞渲染的:“screen”是預設的型別,如果你沒有指定任何型別,預設會給設定成“screen”。因此,第一條和第二條實際上是一樣的。
- 第三條宣告有一個動態的媒介查詢,當頁面正在載入時會對其進行判斷。當頁面載入時跟據裝置的方向來決定portrait.css是否會阻塞渲染。
- 最後一條宣告只用於頁面正在列印時,因此當頁面第一次載入到瀏覽器中時,它不會阻塞渲染。
最後,要記住“阻塞渲染”只與資源是否會阻塞頁面在瀏覽器的初次渲染有關。無論是否阻塞,CSS資源仍然會通過瀏覽器來下載,只是作為一項非阻塞性的低優先順序資源。
瀏覽器渲染阻塞與優化 什麼是阻塞?在頁面中我們通常會引用外部檔案,而瀏覽器在解析HTML頁面是從上到下依次解析、渲染,如果<head>中引用了一個a.js檔案,而這個檔案很大或者有問題,需要2秒載入,那麼瀏覽器會停止渲染頁面(此時是白屏顯示,就是頁面啥都沒有),2秒後加載完成才會繼續渲染,這個就是阻塞。 為什麼會阻塞? 因為瀏覽器不知道a.js中執行了哪些指令碼,會對頁面造成什麼影響,所以瀏覽器會等js檔案下載並執行完成後才繼續渲染,如果這個時間過長,會白屏。 CSS檔案也一樣,因為CSS檔案會對DOM的樣式,佈局,色彩,效果產生影響,所以瀏覽器會等CSS檔案下載並執行完成後繼續。 為了頁面的效能,要避免阻塞。 阻塞優化-推遲載入、非同步載入。 推遲載入(延遲載入) 如果頁面初始的渲染並不依賴於js或者CSS可以用推遲載入,就是最後在載入js和css,把引用外部檔案的程式碼寫在最後。比如一些按鈕的點選事件,比如輪播圖動畫的指令碼也可以放在最後。 原理:因為瀏覽器預設是同步載入(這是為了避免重複觸發“迴流”和“重繪”),此時瀏覽器會從上到下逐條程式碼的載入、解析、渲染、執行。1 <html> 2 <head> 3 </head> 4 <body> 5 xxxxxxxxxxxxxxx 6 <h1>推遲載入</h1> 7 <script type="text/javascript" src="a.js"></script> 8 <link href="a.css" rel="stylesheet" /> 9 </body> 10 </html>defer延遲載入: 在文件解析完成開始執行,並且在DOMContentLoaded事件之前執行完成,會按照他們在文件出現的順序去下載解析。效果和把script放在文件最後</body>之前是一樣的。 注:defer最好用在引用外部檔案中使用,用了defer不要使用document.write()方法;使用defer時最好不要請求樣式資訊,因為樣式表可能尚未載入,瀏覽器會禁止該指令碼等待樣式表載入完成,相當於樣式表阻塞指令碼執行。 非同步載入(非阻塞載入) 注:a.js檔案中的程式碼如下,這樣就會造成阻塞,因為如果我不點選確定,就無法繼續渲染。
1 alert("已暫停載入") 2 alert("開始載入")1)async非同步載入:就是告訴瀏覽器不必等到載入完外部檔案,可以邊渲染邊下載,什麼時候下載完成什麼時候執行。用法就是“async“
1 <script type="text/javascript" src="a.js" async></script>注:實際測試中IE10+才支援,火狐,谷歌,Microsoft支援;用了async不要使用document.write()方法;使用async時最好不要請求樣式資訊,原因和defer一樣。 注2:async 在w3school中介紹是IE9就能支援,而IE9也是號稱能支援,但是實際是不能完全支援的。 2)script dom element法:這個方法是用js動態建立一個script元素新增在document中。 注:支援全部瀏覽器(因為IE低版本IE10- 是單執行緒,所以要修改a.js才能顯示正確的效果)
1 setTimeout("alert('非同步載入成功')",2000) //測試IE時候a.js檔案要修改
1 <script type="text/javascript"> 2 (function() { 3 var s = document.createElement('script'); 4 s.type = 'text/javascript'; 5 s.async = true; //這句可以刪除,但是效果不變。 6 s.src = 'js/a.js'; 7 var x = document.getElementsByTagName('script')[0]; 8 x.parentNode.insertBefore(s, x); 9 })(); 10 </script>注意:這種方法會阻止onload事件,比如下面的程式碼,會等到a.js中的彈出框彈出後再執行。
1 <script type="text/javascript"> 2 window.onload=function(){ 3 document.getElementById('div').innerHTML="onload完成" 4 } 5 </script>3)onload時非同步載入:這個和script dom element法差不多但是他不是同時執行js和html,他是等html的檔案,圖片之類的、頁面所有的資源全部載入完成後再下載執行js,這樣的方法可以避免阻塞onload事件的觸發。(相容所有瀏覽器)
6 //寫在html中
1 (function() { 2 function async_load(){ 3 var s = document.createElement('script'); 4 s.type = 'text/javascript'; 5 s.async = true; 6 s.src = 'js/yibujiaz.js'; 7 var x = document.getElementsByTagName('script')[0]; 8 x.parentNode.insertBefore(s, x); 9 } 10 if (window.attachEvent) 11 window.attachEvent('onload', async_load); 12 else 13 window.addEventListener('load', async_load, false); 14 })();注:DOMContentLoaded與onload事件不同,DOMContentLoaded是頁面解析完成,頁面的dom元素可以使用,但是頁面的圖片、視訊等資源可能還沒載入完成 我上面介紹的優化方式是常用的,除此之外還有其他的,比如非同步載入還有AJAX非同步載入,body onload非同步載入等,這些用的比較少,有興趣的工程師可以去查查相關資料。(如果你在部落格園查基本上只要看一篇文章就好了,其他的基本上都說一樣的,改都不會改;其實全網都差不多,都說互相轉載複製的)。 a.js全部程式碼
1 // setTimeout("alert('非同步載入成功')",2000) 2 // alert("已暫停載入") 3 // alert("開始載入")HTML全部程式碼
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>非同步載入</title> <!-- <script type="text/javascript" src="js/yibujiaz.js" async></script> --> <script type="text/javascript"> (function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.src = 'js/yibujiaz.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })(); </script> <!-- <script type="text/javascript"> (function() { function async_load(){ var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'js/yibujiaz.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); } if (window.attachEvent) window.attachEvent('onload', async_load); else window.addEventListener('load', async_load, false); })(); </script> <script type="text/javascript"> window.onload=function(){ document.getElementById('div').innerHTML="onload完成" } </script> --> <style type="text/css"> div{ width:200px; height:200px; background-color: blue; margin:0 auto; } </style> </head> <body> <div id="div"> </div> </body> </html>