轉載:WEB前端的優化

1、HTML優化

避免使用Iframe

Iframe也叫內聯frame,能夠把一個HTML文檔嵌入到另外一個文檔中。使用iframe的好處是被嵌入的文檔能夠徹底獨立於其父文檔,憑藉此特色咱們一般可使瀏覽器模擬多線程,須要注意的是使用iframe並不會增長同域名下的並行下載數,瀏覽器對同域名的鏈接老是共享瀏覽器級別的鏈接池,即便是跨窗口或跨標籤頁,這在全部主流瀏覽器都是如此。也由於這樣這讓iframe帶來的好處大打折扣。javascript

在頁面加載過程當中iframe元素會阻塞父文檔onload事件的觸發,而開發者程序一般會在onload事件觸發時初始化UI操做。例如,設置登陸區域的焦點。由於用戶習慣等待這一操做,因此儘量的讓onload事件觸發從而使用戶的等待時間變短是很是重要的。另外開發者會把一些重要的行爲綁定在unload事件上,而不幸的是在一些瀏覽器中,只有當onload事件觸發後unload事件才能觸發,若是onload事件長時間未觸發,而用戶已經離開當前頁面,那麼unload事件也將永遠得不到觸發。
那是否有方案可讓onload事件不被iframe阻塞嗎?有個簡單的解決方案來避免onload事件被阻塞,使用JavaScript動態的加載iframe元素或動態設置iframe的src屬性:
php

 <iframe id=iframe1 ></iframe>
 document.getElementById(‘iframe1’).setAttribute(‘src’, ‘url’);

但其僅在高級瀏覽器 中有效,對於Internet Explorer 8及如下的瀏覽器無效。除此以外咱們必須知道iframe是文檔內最消耗資源的元素之一,在Steve Souders 的測試中 ,在測試頁面中分別加載100個A、DIV、SCRIPT、STYLE和 IFRAME元素,而且分別在Chrome、Firefox、Internet Explorer、Opera、Safari中運行了10次。結果顯示建立iframe元素的開銷比建立其餘類型的DOM元素要高1~2個數量級。在測試中全部的DOM元素都是空的,如加載大的腳本或樣式塊可能比加載某些iframe元素耗時更長,但從基準測試結果來看,即便是空的iframe,其開銷也是很是昂貴的,鑑於iframe的高開銷,咱們應儘可能避免使用。尤爲是對於移動設備,對於目前大部分仍是隻有有限的CPU與內存的狀況下,更應避免使用iframe。css

避免空連接屬性

空的連接屬性是指img、link、script、ifrrame元素的src或href屬性被設置了,可是屬性卻爲空。如<img src=」」>,咱們建立了一個圖片,而且暫時設置圖片的地址爲空,但願在將來動態的去修改它。可是即便圖片的地址爲空,瀏覽器依舊會以默認的規則去請求空地址:html

  1. Internet Explorer 8及如下版本瀏覽器只在img類型元素上出現問題,IE會把img的空地址解析爲當前頁面地址的目錄地址。例如:若是當前頁面地址爲http://example.com/dir/page.html,IE會把空地址解析爲http://example.com/dir/地址並請求。
  2. 早些版本的Webkit內核瀏覽器 與Firefox 會把空地址解析爲當前頁面的地址。若是頁面內有多個空連接屬性元素,當前頁面的服務器則會被請求屢次,增長服務器的負載。相較桌面瀏覽器對內核的更新升級較積極,這個問題在ios與android系統的移動瀏覽器上問題可能較嚴重。
  3. 幸運的是全部主流瀏覽器面對iframe的src屬性爲空時,會把空地址解析爲about:blank地址,而不會向服務器發出額外的請求。

避免節點深層級嵌套

深層級嵌套的節點在初始化構建時每每須要更多的內存佔用,而且在遍歷節點時也會更慢些,這與瀏覽器構建DOM文檔的機制有關。例以下面HTML代碼:java

 <html>
 <body>
 <p>
 Hello World
 </p>
 <div> <img src="example.png"/></div>
 </body>
 </html>

經過瀏覽器HTML解析器的解析,瀏覽器會把整個HTML文檔的結構存儲爲DOM樹結構。當文檔節點的嵌套層次越深,構建的DOM樹層次也會越深。android

縮減HTML文檔大小

提升下載速度最顯而易見的方式就是減小文件的大小,特別是壓縮內嵌在HTML文檔中的JavaScript和CSS代碼,這能使得頁面體積大幅精簡。除此以外減小HTML文檔大小還能夠採起下面幾種方法:ios

  1. 刪掉HTM文檔對執行結果無影響的空格空行和註釋
  2. 避免Table佈局
  3. 使用HTML5

顯式指定文檔字符集

HTML頁面開始時指定字符集,有助於瀏覽器能夠當即開始解析HTML代碼。HTML文檔一般被解析爲一序列的帶字符集編碼信息的字符串經過internet傳送。字符集編碼在HTTP響應頭中,或者HTML標記中指定。瀏覽器根據得到的字符集,把編碼解析爲能夠顯示在屏幕上的字符。若是瀏覽器不能獲知頁面的編碼字符集,通常都會在執行腳本和渲染頁面前,把字節流緩存,而後再搜索可進行解析的字符集,或以默認的字符集來解析頁面代碼,這會致使消耗沒必要要的時間。爲了不瀏覽器把時間花費在搜尋合適的字符集來進行解碼,因此最好在文檔中老是顯式的指定頁面字符集。正則表達式

顯式設置圖片的寬高

當瀏覽器加載頁面的HTML代碼時,有時候須要在圖片下載完成前就對頁面佈局進行定位。若是HTML裏的圖片沒有指定尺寸(寬和高),或者代碼描述的尺寸與實際圖片的尺寸不符時,瀏覽器則要在圖片下載完成後再「回溯」該圖片並從新顯示,這會消耗額外時間。因此,最好爲頁面裏的每一張圖片都指定尺寸,無論是在頁面HTML裏的<img>標籤,仍是在CSS裏。express

<img src="hello.png" width="400" height="300">

避免腳本阻塞加載

當瀏覽器在解析常規的script標籤時,它須要等待script下載完畢,再解析執行,然後續的HTML代碼只能等待。爲了不阻塞加載,應把腳步放到文檔的末尾,如把script標籤插入在body結束標籤以前:瀏覽器

 <script src="example.js" ></script>
 </body>

2、高性能 CSS

避免使用@import

有兩種方式加載樣式文件,一種是link元素,另外一種是CSS 2.1加入@import。而在外部的CSS文件中使用@import會使得頁面在加載時增長額外的延遲。雖然規則容許在樣式中調用@import來導入其它的CSS,但瀏覽器不能並行下載樣式,就會致使頁面增添了額外的往返耗時。好比,第一個CSS文件first.css包含了如下內容:@import url(「second.css」)。那麼瀏覽器就必須先把first.css下載、解析和執行後,才發現及處理第二個文件second.css。簡單的解決方法是使用<link>標記來替代@import,好比下面的寫法就可以並行下載CSS文件,從而加快頁面加載速度:

<link rel="stylesheet" href=""first.css"" />
<link rel="stylesheet" href="second.css" />

須要注意的是一個頁面中的CSS文件不宜過多,不然應該簡化及合併外部的CSS文件以節省往返請求時間(RTT)提高頁面加載速度。

避免AlphaImageLoader濾鏡

IE獨有屬性AlphaImageLoader用於修正7.0如下版本中顯示PNG圖片的半透明效果。這個濾鏡的問題在於瀏覽器加載圖片時它會終止內容的呈現而且凍結瀏覽器。在每個元素(不只僅是圖片)它都會運算一次,增長了內存開支,所以它的問題是多方面的。徹底避免使用AlphaImageLoader的最好方法就是使用PNG8格式來代替,這種格式能在IE中很好地工做。若是你確實須要使用AlphaImageLoader,請使用下劃線_filter又使之對IE7以上版本的用戶無效。

避免CSS表達式

CSS表達式是動態設置CSS屬性的強大(但危險)方法。Internet Explorer從第5個版本開始支持CSS表達式。下面的例子中,使用CSS表達式能夠實現隔一個小時切換一次背景顏色:

background-color: expression((new Date()).getHours()%2?"#FFFFFF": "#000000" );

如上所示,expression中使用了JavaScript表達式。CSS屬性根據JavaScript表達式的計算結果來設置。expression方法在其它瀏覽器中不起做用,所以在跨瀏覽器的設計中單獨針對Internet Explorer設置時會比較有用。

表達式的問題就在於它的計算頻率要比咱們想象的多。不只僅是在頁面顯示和縮放時,就是在頁面滾動、乃至移動鼠標時都會要從新計算一次。給CSS表達式增長一個計數器能夠跟蹤表達式的計算頻率。在頁面中隨便移動鼠標均可以輕鬆達到10000次以上的計算量。一個減小CSS表達式計算次數的方法就是使用一次性的表達式,它在第一次運行時將結果賦給指定的樣式屬性,並用這個屬性來代替CSS表達式。若是樣式屬性必須在頁面週期內動態地改變,使用事件句柄來代替CSS表達式是一個可行辦法。若是必須使用CSS表達式,必定要記住它們要計算成千上萬次而且可能會對你頁面的性能產生影響。

避免通配選擇器

CSS選擇器對性能的影響源於瀏覽器匹配選擇器和文檔元素時所消耗的時間,因此優化選擇器的原則是應儘可能避免須要消耗更多匹配時間的選擇器。而在這以前咱們須要瞭解CSS選擇器匹配的機制,如例子的子選擇器規則:

#header > a {font-weight:blod;}

咱們中的大多數人都是從左到右的閱讀習慣,可能也會習慣性的設定瀏覽器也是從左到右的方式進行匹配規則,由於會推測這條規則的開銷並不高。咱們這樣假象瀏覽器會像這樣的方式工做:找到惟一的id爲header爲的元素,而後把這個樣式規則應用到直系子元素中的a元素上。咱們知道文檔中只有一個id爲header的元素,而且它只有幾個a類型的子節點,因此這個CSS選擇器應該至關高效。

事實上,卻剛好相反,CSS選擇器是從右到左進行規則匹配。瞭解這個機制後,例子中看似高效的選擇器在實際中的匹配開銷是很高的,瀏覽器必須遍歷頁面中全部的a元素而且肯定其父元素的id是否爲header。

若是把例子的子選擇器改成後代選擇器則會開銷更多,在遍歷頁面中全部a元素後還需向其上級遍歷直到根節點。

#header a {font-weight:blod;}

理解了CSS選擇器從右到左匹配的機制後,能夠理解選擇器中最右邊的規則每每決定了瀏覽器繼續左移匹配的工做量,咱們把最右邊選擇規則稱之爲關鍵選擇器。

通配選擇器使用 * 符合表示,可匹配文檔中的每個元素。以下例規則將全部元素的字體大小設置爲20px:

* { font-size:20px;}

通配選擇器做用於全部的元素,如規則最右邊爲通配符:

.selected * {color: red;}

瀏覽器匹配文檔中全部的元素後分別向上逐級匹配class爲selected的元素,直到文檔的根節點,所以其匹配開銷是很是大的,一般比開銷最小的ID選擇器高出1~3個數量級,因此應避免使用關鍵選擇器是通配選擇器的規則。

避免單規則的屬性選擇器

屬性選擇器根據元素的屬性是否存在或其屬性值進行匹配,以下例規則會把herf屬性值等於」#index」的連接元素設置爲紅色:

.selected [href=」#index」] {color: red;}

但其匹配開銷是很是大的,瀏覽器先匹配全部的元素,檢查其是否有href屬性而且herf屬性值等於」#index」, 而後分別向上逐級匹配class爲selected的元素,直到文檔的根節點。因此應避免使用關鍵選擇器是單規則屬性選擇器的規則。

避免類正則的屬性選擇器

CSS3添加了複雜的屬性選擇器,能夠經過類正則表達式的方式對元素的屬性值進行匹配。固然這些類型的選擇器定是會影響性能的,正則表達式匹配會比基於類別的匹配會慢不少。大部分狀況下咱們應儘可能避免使用 *=, |=, ^=, $=, 和 ~=語法的屬性選擇器。

移除無匹配的樣式

移除無匹配的樣式,有兩個好處:

第一,刪除無用的樣式後能夠縮減樣式文件的體積,加快資源下載速度;

第二,對於瀏覽器而言,全部的樣式規則的都會被解析後索引發來,即便是當前頁面無匹配的規則。移除無匹配的規則,減小索引項,加快瀏覽器查找速度;

3、高性能 JavaScript

使用事件代理

有時候咱們會感受到頁面反應遲鈍,這是由於DOM樹元素中附加了過多的事件句柄而且些事件句病被頻繁地觸發。這就是爲何說使用事件代理是一種好方法了。若是你在一個div中有10個按鈕,你只須要在div上附加一次事件句柄就能夠了,而不用去爲每個按鈕增長一個句柄。事件冒泡時你能夠捕捉到事件並判斷出是哪一個事件發出的。

緩存選擇器查詢結果

選擇器查詢是開銷很大的方法。因此,使用選擇器的次數應該越少越好,而且儘量緩存選中的結果,便於之後反覆使用。好比,下面這樣的寫法就是糟糕的寫法:

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是同步的,且cookie與localstorage是多個tab頁面間共享的,多頁面同時操做時會存在同步加鎖機制,建議應儘可能少的對cookie或localStorage進行操做。

避免頻繁的DOM操做

使用JavaScript訪問DOM元素是比較慢的,所以爲了提高性能,應該作到:

  1. 緩存已經查詢過的元素;
  2. 線下更新完節點以後再將它們添加到文檔樹中;
  3. 避免使用JavaScript來修改頁面佈局;

使用微類庫

一般開發者都會使用JavaScript類庫,如jQuery、Mootools、YUI、Dojo等,可是開發者每每只是使用JavaScript類庫中的部分功能。爲了更大的提高性能,應儘可能避免使用這類大而全的類庫,而是按需使用微類庫來輔助開發。

相關文章
相關標籤/搜索