網站性能,javascript性能相關知識點

1、高性能網站

《高性能網站建設指南》一書中提出用戶只有10%-20%最終用戶響應時間是花在從web服務器獲取html文檔並傳送到瀏覽器中,80%的時間都花在了等待頁面組件中,由此提出了構建高性能網站的14個規則。按照優先級排序依次是:javascript

1.減小http請求數css

直接方法是減小組件的個數,由此來減小http請求數量,能夠採用的方法包括圖片地圖,css sprites(利用css的background-position屬性,能夠講html元素放置到背景圖片中指望的位置上),樣式表的合併等等。html

2.使用內容發佈網絡CDNjava

CDN用於發佈靜態內容,包括圖片,腳本,樣式表,和flash。node

3.添加expires頭web

條件GET請求和304響應有助於讓頁面加載得更快,然而仍然須要在客戶端和服務器進行一次往返確認。expries頭部經過明確指出瀏覽器是否可使用組件的緩存副原本消除這個須要。經過服務器會返回一個expires頭。expires:thu 15.。。當瀏覽器看到響應有一個expries頭時,它會和響應的組件一塊兒保存在緩存中,只要組件沒有過時,就不會發生任何http請求。ajax

長久的expries頭部應該包含任何不常常變化的組件,包括腳本,樣式表和flash組件。這一般是在服務器的配置文件中配置。與之相似的另外一個http頭部是cache-control:max-age.若是兩者同時出現,http規範規定max-age指令將重寫expire頭。chrome

若是確保用戶能獲取最新的組件,最有效的解決方案是修改器全部連接。所以爲全部組件的命名最好採用變量。apache

4.壓縮組件編程

客戶端經過appect-encoding:gzip,deflate來表示對壓縮的支持,html,文檔,樣式表一般是值得壓縮的。圖片和pdf不該該壓縮,由於它們原本就已經壓縮了,試圖再次壓縮不只浪費CPU資源,還可能會增長文件大小。

服務器端在apache的配置文件中進行配置。

5.將樣式表放在頂部

將樣式表放在底部會致使在瀏覽器中阻止內容逐步呈現,出現白屏或者FOUC(無樣式內容閃爍,即內容呈現後,待樣式表加載完成再次重繪)。

6.將腳本放在底部或者採用無阻塞腳本

通常,http規範建議每一個主機名能夠並行下載兩個組件(注意,僅僅是建議)。可是在下載腳本時,並行下載是被禁用的,頁面的下載和與渲染都必須停下來等待腳本下載和執行完成。這一方面是爲了保證腳本的正確執行順序,另外一方面是爲了防止document.write修改頁面。所以最好將樣式表放在底部。

此外,能夠採用無阻塞腳本(在頁面加載完成以後才加載javascript代碼,意味着在DOMContentLoaded事件,或者window的load事件觸發後再下載腳本,此時腳本能夠放在頁面任何位置)的方法有:

1)延遲的腳本

爲script標籤添加defer或者async屬性,用於異步加載腳本。兩者的相同點是採用並行加載,在下載過程當中不會產生阻塞。不一樣點在於執行時機,async是加載完成後自動執行,而defer須要等到頁面加載完成才執行。

2)動態腳本元素

var script=document.createElement('script');
script.type='type/javascript';
script.src='file1.js';
document.getElementsByTagName('head')[0].append('script');

動態腳本可用來實現jsonP。此外,也能夠實現腳本的無阻塞加載。文件在元素被添加到頁面時開始下載。不管什麼時候啓動下載,文件的下載和執行均不會阻塞頁面其餘進程。使用動態腳本節點下載文件時,返回的代碼一般會當即執行。若是加載多個動態腳本,只有firefox和opera會保證腳本按照指定的順序執行,其餘瀏覽器則會按照服務器返回的順序下載和執行。

動態腳本加載憑藉其跨瀏覽器的優點,成爲最通用的無阻塞加載的解決方案。使用這種方法須要兩步驟:先添加動態加載所須要的代碼,而後加載初始化頁面所須要的其餘腳本。下面是一個經過的無阻塞加載的方法:

function loadScript(url,callback){
    var script=document.createElement('script');    
    script.type='type/javascript';
    script.src=url;
    if(script.readyState){//IE
        script.onreadystatechange=function(){
            if(script.readyState==='loaded'||script.readyState==='complete'){
                script.readyState=null;
                callback();
            }
        }
    }else{
        script.onload=function(){
            callback();
        }
    }
    document.getElementsByTagName('head')[0].appendChild(script);
}

7.避免CSS表達式

這個通常都不會這麼作了,所以不展開詳細說明了。

8.使用外部javascript和css

使用外部文件,可緩存,可重用。

9,減小DNS查找,

經過keep-alive和較少的域名來減小DNS查找。瀏覽器有DNS的緩存,操做系統也有DNS的緩存,減小惟一主機名會減小DNS查找次數,但同時也減小了頁面中並行下載的數量,所以建議將組件分別放到至少2個,至多4個主機名下,達到兩者的權衡。

10.精簡javscript

方法有兩種:壓縮(去除空白等),混淆(使用更短的變量、函數名)

11.避免重定向

http狀態碼如301,302表明重定向,304不是真正的重定向,只是響應條件GET請求,避免下載已經存在在緩存中的數據。一種重定向最爲浪費,發生在URL結尾必須出現/卻沒有出現的時候(容許自動索引到index.html的狀況下),注意主機名後面缺乏斜線並不會引發重定向。如www.baidu.com

重定向延遲了整個html文檔的傳輸,在html文檔到達以前,頁面不會呈現任何東西,也沒有任何組件被下載。

12.刪除重複腳本

引入腳本模塊化管理,防止同一個腳本屢次引入。

13.配置ETag

若是緩存的組件到期了(或者用戶refresh或者reload了頁面),瀏覽器會發送一個條件GET請求,若是瀏覽器檢測到緩存的組件是有效的,原始服務器不會返回整個組件,而是返回一個304碼。

服務器檢測緩存的組件是否和原始服務器的組件匹配時有兩種方式:

1)比較最新修改日期

條件get請求的請求頭包含IF-MODIFED-SINCE頭部,響應頭包含LAST-MODIFED頭部,經過比較來判斷

2)實體標籤ETAG

ETAG提供了另一種方式,用於檢測瀏覽器緩存中的組件與原始服務器的組件是否匹配(實體是組件的另外一種稱呼)。這種方式的http 條件GET請求會返回一個ETAG頭部。

ETAG提供了另一種方式,ETAG一般基於實體的某些屬性來構造,實體的狀態能夠反映在ETAG中,對於特定的,寄宿了網站的服務器來講是惟一的。Apache中ETAG的格式是innode-size-timestamp,文件系統採用innode來存儲諸如文件類型,全部者等信息。所以ETAG的問題是,當從一臺服務器獲取了原始組件,當向另外一臺服務器發送條件GET請求時,ETAG是不會匹配的,這對於集羣服務器來講很常見。所以最好服務器移除或者配置默認的ETAG。

14.使ajax請求結果可緩存

2、高性能javascript

回到javascript自身的性能問題,很贊同《你不知道的javascript(中卷)》中的一句話,不要沉迷於微性能的調優,好比a++和++a。應該關注優化的大局,即代碼是否運行在關鍵路徑上。所謂關鍵路徑,好比用戶會注意到的UX關鍵位置,如動畫循環或css風格更新,或者一段會運行屢次的「熱」代碼等。

1.數據訪問

訪問字面量和局部變量速度最快,訪問數組元素和對象成員相對較慢。局部變量存在做用域鏈其實位置,所以最快,全局變量最慢。所以能夠把經常使用的對象成員,數組元素,跨域變量保存在局部變量中來該刪javascript性能。

2.DOM編程

  2.1DOM模型

文檔對象模型(DOM)是一個獨立於語言的,用於操做XML和HTML文檔的程序接口(API)。儘管DOM是個和語言無關的API,可是它在瀏覽器中的接口是javascrcipt實現的。瀏覽器一般會把DOM和javascript(這裏指ECMAscript)獨立實現,好比chrome使用Webkit來渲染頁面,但javascript引擎則是他們本身開發的,命名爲V8.所以DOM編程中一個通用的作法是,儘可能減小DOM訪問次數,把運算儘可能留在ECMAscript這一端。

  2.2HTML集合

html集合是包含了DOM節點引用的類數組對象,如下方法返回的就是html集合:

 

document.getElementsByTagName
document.getElementsByClassName
document.getElementsByName

 

此外,如下屬性也一樣返回html集合:

document.images
document.links
document.forms
document.forms[0].elements

html集合是類數組的列表,它們並非真的數組,不具備數組的push,slice等方法,可是具備length屬性,也可使用數字下標訪問元素。

根據DOM標準的定義,html集合一直和文檔保持聯繫,文檔更新時,他們也會自動更新,這意味着,每次須要最新的信息時,都會重複執行查詢的過程,哪怕只是獲取集合中的元素個數(即length屬性),也是如此,這就形成了低效之源。例如,下面的代碼會陷入死循環:

 

var allDivs=document.getElementsByTagName('div');
for(var i=0;i<allDivs.length;i++){
  document.body.appendChild(document.createElement('div'));  
}

 

此時建議將集合的長度緩存到一個變量中,若是常常操做集合,能夠將它拷貝到一個數組中。

  2.3重繪與重排

javascript在下載完全部組件(html,js,css,圖片)後會生成兩個內部的數據結構:DOM樹(表示頁面結構),渲染樹(表示DOM節點如何展現)。

當DOM變化影響了元素的幾何屬性時(寬和高)時,瀏覽器會使得渲染樹中受到影響的部分失效,就會發生重排。重排以後,會將受影響的部分從新繪製到屏幕中,稱爲重繪。若是沒有影響幾何屬性,如僅僅改變了背景色,那麼只會發生重繪。

重排和重繪代價可能很是昂貴,所以要儘可能減小其次數。當須要對DOM元素進行一系列操做時,可採用如下步驟:

1).使元素脫離文檔流。

脫離文檔的方法有如下幾種:

  A. 隱藏元素,應用修改,從新顯示;

  B.使用文檔片斷,在當前DOM以外構建一棵子樹,再把它拷貝到文檔中。

  C.使用絕對定位,好比對動畫元素使用絕對定位,當動畫結束時恢復定位。  

2).對其應用多重改變。

3).將元素帶回文檔。

 

3.快速響應的用戶界面

用於執行javascript和更新用戶界面的進程一般被稱爲「瀏覽器UI線程」。

通常瀏覽器會限制javascript任務的運行時間,有的瀏覽器採用調用棧大小限制(好比500萬條語句),有的採用長時間限制(好比100ms)。當遭遇這種狀況時,考慮的解決方法有兩種:

1)分時函數和延遲函數

 參見以前博客:http://www.cnblogs.com/bobodeboke/p/5594647.html

2)web workers,這是js新引入的特性,每一個work在一個獨立線程中執行,不會形成阻塞。可是web workers直接訪問DOM會出現錯誤,所以適用於解決數據計算,解析等費時的操做。

相關文章
相關標籤/搜索