高性能HTML
一、避免使用iframe
iframe也叫內聯frame,可將一個HTML文檔嵌入另一個HTML文檔中。
iframe的好處是,嵌入的文檔獨立於父文檔,通常也借此使瀏覽器模擬多線程。缺點是:
①雖然iframe能模擬多線程,但主流瀏覽器的同域名並行下載數是不變的,瀏覽器對同域名的鏈接總是共享瀏覽器級別的連接池,
即使是不同窗口或標簽頁的同域名網頁。
②在頁面加載時,iframe會阻塞父文檔onload事件的觸發。並且有些瀏覽器需在觸發onload事件后才能被觸發onunload事件。
故用戶用onload事件長久未觸發而離開頁面時,不會觸發onunload事件。
※不兼容IE6~8的解決方案:使用JavaScript動態加載iframe元素或動態設置其src屬性。
<iframe id=ifr ></iframe> document.getElementById( ‘ifr’ ).setAttribute( ‘src’ , ‘url ’ );
③iframe是文檔內最消耗資源的元素之一,即使是空iframe的開銷也是昂貴的。【通過Steve Souders測試】
二、避免空連接屬性
空連接指:img、link、script 和 iframe元素的src或href屬性的值為空。(如src = ””)
設置了空連接后瀏覽器依然會以默認規則發送請求:
①IE6~8中只有img元素會出問題:IE會將img的空地址解析為當前頁面地址的目錄地址並請求。
如當前網頁地址為http://aaa.com/bb/c.html,img的地址會被解析為http://aaa.com/bb
②早些版本的Webkit和Firefox會將空連接解析為當前頁面的地址。在ios與android中此問題較嚴重。
如果頁面有多個空連接屬性元素,會增加服務器的請求次數。
③幸運的是,主流瀏覽器對iframe的src屬性值為空時,會解析為about:blank地址,而不發送額外請求。
三、避免節點深層級嵌套
層級越深的節點在初始化構建時,所占內存越多。
通過瀏覽器HTML解析器會將整個HTML文檔的結構存儲為DOM樹結構。當節點嵌套層次越深,構建的DOM書層次也越深。
四、縮減HTML文檔大小
①刪除對執行結果無影響的空格空行和注釋;
②避免table布局;
③使用HTML5;
五。顯式指定文檔字符集
在HTML頁面開時指定字符集有助於瀏覽器立即開始解析HTML代碼。
HTML文檔通常被解析為一序列的帶字符集編碼信息的字符串,通過Internet傳送。
字符集編碼在HTTP響應頭中,或HTML標記中指定。瀏覽器通過指定的字符集,吧編碼解析為可現實在屏幕上的字符。
若瀏覽器無法獲知頁面的編碼字符集,一般會在執行腳本和渲染頁面之前,先將字節流緩存,再搜索可進行解析的字符集 或 以默認字符集來解析。
六、顯示設置圖片的寬高
有時需要在頁面加載完之前,就對頁面布局進行定位。
若頁面中的圖片沒指定尺寸,或尺寸與實際圖片大小不符,瀏覽器會在圖片下載完成后再"回溯"該圖片並重新顯示,從而浪費時間。
故最好為頁面的圖片設置指定尺寸(行內樣式或CSS樣式)。
<img src="hello.png" width="400" height="300">
七、避免 腳本阻塞加載
瀏覽器在解析常規script標簽時,會等待script下載完畢后,才解析執行,之后的HTML代碼就只能等待。
故應該將腳本放在文檔的末尾:
<script src="example.js" ></script> </body>
高性能CSS
一、避免使用@import
CSS2.1加入的@import,會使頁面在加載時添加額外延遲。
由於瀏覽器不能並行下載樣式,會導致頁面增添額外的往返耗時。而使用<link>能並行下載樣式,但任然是多次請求。
二、避免AlphaImageLoader濾鏡
此濾鏡能解決IE6即一下版本顯示PNG圖片的半透明效果,但會在加載圖片時終止內容的呈現,並凍結瀏覽器。
在每個元素(不僅僅是圖片)都會運算一次,添加內存開支。
應使用PNG8格式來代替,或用下划線(_filter)只針對IE6。
三、避免CSS表達式
CSS表達式是設置動態CSS屬性的即強調又危險的方法。IE5開始支持,IE獨有。
//實現每隔一小時切換一次背景顏色 background-color: expression((new Date()).getHours()%2?"#FFFFFF": "#000000" );
CSS表達式的缺點是技術頻率極大,在頁面顯示、縮放、滾動 或 移動鼠標,都會重新計算一次。移動隨便會達到1w次以上的計算量。
①使用一次性的表達式能減少計算次數,在第一次運行時將結果賦給指定樣式屬性,並用該屬性代替CSS表達式。
②如果樣式屬性必須在頁面周期內動態地改變,使用時間句柄代替CSS表達式是一個可行的辦法。
優化選擇器的原則是減少匹配時間。CSS選擇器的匹配機制是:從右向左進行規制匹配的!
#header > a { font-weight:blod; }
上面這條規制實際是瀏覽器遍歷頁面所有a元素,並確定其父元素的id是否為header。
#header a {...}
后代選擇器開銷更大,在遍歷頁面的所有a元素后,會需向上遍歷直到根節點。
由此可知,選擇器最右邊的規制 往往決定了向左移匹配的工作量。故最右邊的選擇規則 稱之為關鍵選擇器。
.selected * {...}
在匹配所有元素后,再分別向上匹配直至根節點。通常比開銷最小的ID選擇器高出·~3個數量級。
五、避免單規則的屬性選擇器
.selected [href='#index'] {...}
瀏覽器先匹配所有的元素,檢查其是否有href屬性並且值為“#index”,再分別向上匹配class為selected的元素。
故應該避免使用關鍵選擇器是單規則屬性選擇器的規則。
六、避免正則的屬性選擇器
CSS3添加了復雜的屬性選擇器,通過類正則表達式進行匹配。但這些類型的選擇器會比基於類別的匹配慢很多。
七、移除無匹配的樣式
①刪除無用的樣式,可縮減樣式文件大小,加快加載速度。
②對於瀏覽器,所有樣式規則都會被解析后索引起來,即使是當前頁面無匹配的規則!故移除無匹配的規則,減少索引項,加快瀏覽器查找速度。
高性能JavaScript
一、使用事件代理
當過多的時間句柄被頻繁觸發時,頁面反應會遲鈍。
如一個div有10個按鈕,只需給div附加一次事件句柄,而不必給每個按鈕添加一個句柄。
事件冒泡時刻捕捉到事件 並判斷時那個事件發出的。【觸發事件的元素 = ev.srcElement ? ev.srcElement : ev.target;】
二、緩存選擇器查詢結果
減少選擇器查詢的次數,並盡可能緩存選中的結果,便於以后的重用。
jQuery('#top').find('p.classA'); ... jQuery('#top').find('p.classB'); //使用下面的方法 減少開銷 var cached = jQuery('#top'); cached.find('p.classA'); ... cached.find('p.classB');
三、避免頻繁的IO操作
應減少對cookie或localstorage的操作,因為對它們進行操作的API是同步的,而它們是多個tab頁面間共享的。
多頁面同時操作cookie和localstorage時,會存在同步加鎖機制。
四、避免頻繁的DOM操作
JavaScript訪問DOM元素緩慢,應做到:
①緩存已經查詢過的元素;
②線下更新完節點之后,在將它們添加到文檔樹中;
③避免使用JavaScript來修改頁面布局。
五、使用微類庫
盡量避免使用大而全的類庫,而是按需使用微類庫來輔助開發。
本文整理自:http://madscript.com/performance/high-performance-frontend/