摘要:無論是在工作中,還是在面試中,web前端效能的最佳化都是很重要的,那麼我們進行最佳化需要從哪些方面著手呢?可以遵循雅虎的前端優化34條軍規,不過現在已經是35條了,所以可以說是雅虎前端優化的35條軍規。已分類,挺好的,這樣對於優化有一個比較清晰的方向
內容部分1.盡量減少HTTP請求數80%的終端使用者回應時間都花在了前端上,其中大部分時間都在下載頁面上的各種元件:圖片,樣式表,腳本,Flash等等。減少元件數必然能夠減少頁面提交的HTTP請求數。這是讓頁面更快的關鍵。
減少頁面元件數的一種方法是簡化頁面設計。但有沒有一種方法可以在建立複雜的頁面同時加快回應時間呢?嗯,確實有魚和熊掌兼得的辦法。
合併文件是透過把所有腳本放在一個文件中的方式來減少請求數的,當然,也可以合併所有的CSS。如果各個頁面的腳本和樣式不一樣的話,合併文件就是一項比較麻煩的工作了,但把這個作為網站發布過程的一部分確實可以提高響應時間。 CSS Sprites是減少圖片請求數量的首選方式。把背景圖片都整合到一張圖片中,然後用CSS的background-image和background-position屬性來定位要顯示的部分。圖像映射可以把多張圖片合併成單張圖片,總大小是一樣的,但減少了請求數並加速了頁面載入。圖片映射只有在圖像在頁面中連續的時候才有用,例如導航條。為image map設定座標的過程既無聊又容易出錯,用image map來做導航也不容易,所以不建議用這種方式。行內圖片(Base64編碼)用data: URL模式來把圖片嵌入頁面。這樣會增加HTML檔案的大小,把行內圖片放在(快取的)樣式表中是個好辦法,而且成功避免了頁面變重。但目前主流瀏覽器並不能很好地支援行內圖片。減少頁面的HTTP請求數是個起點,這是提升網站首次存取速度的重要指導原則。
2.減少DNS查找網域名稱系統建立了主機名稱和IP位址間的映射,就像電話簿上人名和號碼的映射一樣。當你在瀏覽器輸入www.yahoo.com的時候,瀏覽器就會聯絡DNS解析器回伺服器的IP位址。 DNS是有成本的,它需要20到120毫秒去尋找給定主機名稱的IP位址。在DNS查找完成之前,瀏覽器無法從主機名稱下載任何東西。
DNS查找被快取起來更有效率,由使用者的ISP(網路服務供應商)或本地網路存在一個特殊的快取伺服器上,但也可以快取在個人使用者的電腦上。 DNS資訊被保存在作業系統的DNS cache(微軟Windows上的DNS客戶端服務)裡。大多數瀏覽器有獨立於作業系統的自己的cache。只要瀏覽器在自己的cache裡還保留著這條記錄,它就不會向作業系統查詢DNS。
IE預設快取DNS查找30分鐘,寫在DnsCacheTimeout註冊表設定中。 Firefox快取1分鐘,可以用network.dnsCacheExpiration設定項目設定。 (Fasterfox把快取時間改成了1小時PS Fasterfox是FF的一個加速插件)
如果客戶端的DNS cache是空的(包括瀏覽器的和作業系統的),DNS查找數等於頁面上不同的主機名數,包括頁面URL,圖片,腳本文件,樣式表,Flash物件等等元件中的主機名,減少不同的主機名稱就可以減少DNS查找。
減少不同主機名稱的數量同時也減少了頁面能夠並行下載的組件數量,避免DNS查找削減了響應時間,而減少並行下載數量卻增加了響應時間。我的原則是把元件分散在2到4個主機名稱下,這是同時減少DNS查找和允許高並發下載的折中方案。
3.避免重定向重定向用301和302狀態碼,下面是一個有301狀態碼的HTTP頭:
HTTP/1.1 301 Moved PermanentlyLocation: http://example.com/newuriContent-Type: text/html
瀏覽器會自動跳到Location域所指明的URL。重定向所需的所有資訊都在HTTP頭部,而響應體一般是空的。其實額外的HTTP頭,像是Expires和Cache-Control也表示重定向。除此之外還有別的跳轉方式:refresh元標籤和JavaScript,但如果你必須要做重定向,最好用標準的3xxHTTP狀態碼,主要是為了讓回傳按鈕能正常使用。
牢記重定向會拖慢使用者體驗,在使用者和HTML文件之間插入重定向會延遲頁面上的所有東西,頁面無法渲染,元件也無法開始下載,直到HTML文件被送達瀏覽器。
有一種常見的極度浪費資源的重定向,而且web開發人員一般都意識不到這一點,就是URL尾部缺少一個斜線的時候。例如,跳到http://astrology.yahoo.com/astrology會回到一個重新導向到http://astrology.yahoo.com/astrology/的301回應(注意添在尾部的斜線)。在Apache中可以用Alias,mod_rewrite或DirectorySlash指令來取消不必要的重定向。
重定向最常見的用途是把舊站點連接到新的站點,還可以連接同一站點的不同部分,針對用戶的不同情況(瀏覽器類型,用戶帳號類型等等)做一些處理。用重定向來連接兩個網站是最簡單的,只需要少量的額外程式碼。雖然在這些時候使用重定向減少了開發人員的開發複雜度,但降低了使用者體驗。一個替代方案是用Alias和mod_rewrite,前提是兩個程式碼路徑都在相同的伺服器上。如果是因為網域變更而使用了重新導向,就可以建立一條CNAME(建立一個指向另一個網域的DNS記錄作為別名)結合Alias或mod_rewrite指令。
4.讓Ajax可緩存Ajax的一個好處是可以提供使用者即時回饋,因為它能夠從後台伺服器非同步請求資訊。然而,用了Ajax就無法保證用戶在等待非同步JavaScript和XML回應返回期間不會非常無聊。在許多應用程式中,使用者能夠一直等待取決於如何使用Ajax。例如,在基於web的電子郵件用戶端中,使用者為了尋找符合他們搜尋標準的郵件訊息,將會保持對Ajax請求回傳結果的關注。重要的是,要記得非同步並不意味著即時。
要提高效能,優化這些Ajax響應至關重要。最重要的提升Ajax效能的方法就是讓回應變得可緩存,就像在添上Expires或Cache-Control HTTP頭中討論的一樣。下面適用於Ajax的其它規則:
我們一起看看例子,一個Web 2.0的電子郵件用戶端用了Ajax來下載使用者的通訊錄,以便實現自動完成功能。如果使用者從上次使用之後再沒有修改過她的通訊錄,而且Ajax回應是可快取的,有尚未過期的Expires或Cache-Control HTTP頭,那麼之前的通訊錄就可以從快取中讀出。必須通知瀏覽器,應該繼續使用先前快取的通訊錄回應,還是去請求一個新的。可以透過在通訊錄的Ajax URL裡添加一個表明用戶通訊錄最後修改時間的時間戳來實現,例如&t=1190241612。如果通訊錄從上一次下載之後再沒有被修改過,時間戳不變,通訊錄就將從瀏覽器快取中直接讀出,從而避免一次額外的HTTP往返消耗。如果使用者已經修改了通訊錄,時間戳記也可以確保新的URL不會符合快取的回應,瀏覽器會要求新的通訊錄條目。
即使Ajax回應是動態創建的,而且可能只適用於單一用戶,它們也可以被緩存,而這樣會讓你的Web 2.0應用更快。
5.延遲載入組件可以湊近看看頁面並問自己:什麼是一開始渲染頁面所必須的?其餘內容都可以等會兒。
JavaScript是分隔onload事件之前和之後的理想選擇。例如,如果有JavaScript程式碼和支援拖放以及動畫的庫,這些都可以先等會兒,因為拖放元素是在頁面最初渲染之後的。其它可以延遲載入的部分包括隱藏內容(在某個互動動作之後才出現的內容)和折疊的圖片。
工具可幫你減輕工作量:YUI Image Loader可以延遲載入折疊的圖片,還有YUI Get utility是一種引入JS和CSS的簡單方法。 Yahoo!主頁就是一個例子,可以打開Firebug的網路面板仔細看看。
最好讓效能目標符合其它web開發最佳實踐,例如漸進增強。如果用戶端支援JavaScript,可以提高使用者體驗,但必須確保頁面在不支援JavaScript時也能正常運作。所以,在確定頁面運作正常之後,可以用一些延遲載入腳本來增強它,以支援一些拖放和動畫之類的華麗效果。
6.預加載組件
預載可能看起來和延遲載入是相反的,但它其實有不同的目標。透過預先載入元件可以充分利用瀏覽器空閒的時間來請求將來會用到的元件(圖片,樣式和腳本)。用戶造訪下一頁的時候,大部分元件都已經在快取裡了,所以在使用者看來頁面會載入得更快。
實際應用中有以下幾種預先載入的類型:
一個複雜的頁面意味著要下載更多的字節,而且用JavaScript存取DOM也會更慢。舉個例子,想要加入一個事件處理器的時候,循環遍歷頁面上的500個DOM元素和5000個DOM元素是有差別的。
大量的DOM元素是一種徵兆-頁面上有些內容無關的標記需要清理。正在用巢狀表格來佈局嗎?還是為了修復版面問題而添了一堆的<div>s?或許應該用更好的語意化來標記。
YUI CSS utilities對佈局有很大幫助:grids.css針對整體佈局,fonts.css和reset.css可以用來去除瀏覽器的預設格式。這是個開始清理和思考標記的好機會,例如只在語義上有意義的時候使用<div>,而不是因為它能夠渲染一個新行。
DOM元素的數量很容易測試,只需要在Firebug的控制台輸入:
document.getElementsByTagName('*').length那麼多少DOM元素才算太多呢?可以參考其它類似的標記良好的頁面,例如Yahoo!主頁是一個相當繁忙的頁面,但只有不到700個元素(HTML標籤)。
8.跨域分離元件分離元件可以最大化並行下載,但確保只用不超過2-4個網域,因為存在DNS查找的代價。例如,可以把HTML和動態內容部署在www.example.org,而把靜態元件分離到static1.example.org和static2.example.org。
9.盡量少用iframe用iframe可以把一個HTML文件插入到父文檔裡,重要的是明白iframe是如何運作的並且有效率地使用它。
<iframe>的優點:
<iframe>的缺點:
HTTP請求代價高昂,完全沒有必要用一個HTTP請求去取得一個無用的回應(例如404 Not Found),只會拖慢使用者體驗而沒有任何好處。
有些站點用的是有幫助的404-你的意思是xxx? ,這樣做有利於使用者體驗,,但也浪費了伺服器資源(例如資料庫等等)。最糟糕的是連結到的外部JavaScript有錯誤而且結果是404。首先,這種下載將會阻塞並行下載。其次,瀏覽器會試圖解析404響應體,因為它是JavaScript程式碼,需要找出其中可用的部分。
css部分11.避免使用CSS表達式用CSS表達式動態設定CSS屬性,是一種強大又危險的方式。從IE5開始支持,但從IE8起就不建議使用了。例如,可以用CSS表達式把背景顏色設定成按小時交替的:
background-color: expression( (new Date()).getHours()%2 ? #B8D4FF : #F08A00 );12.選擇<link>捨棄@import
前面提到了一個最佳實踐:為了實現逐步渲染,CSS應該放在頂部。
在IE中用@import與在底部用<link>效果一樣,所以最好不要用它。
13.避免使用濾鏡IE專有的AlphaImageLoader濾鏡可以用來修復IE7之前的版本中半透明PNG圖片的問題。在圖片載入過程中,這個濾鏡會阻塞渲染,卡住瀏覽器,還會增加記憶體消耗而且是被應用到每個元素的,而不是每個圖片,所以會存在一大堆問題。
最好的方法是乾脆不要用AlphaImageLoader,而優雅地降級到用在IE中支持性很好的PNG8圖片來代替。如果要用AlphaImageLoader,應該用底線hack:_filter來避免影響IE7及更高版本的使用者。
14.把樣式表放在頂部在Yahoo!研究效能的時候,我們發現把樣式表放到文件的HEAD部分能讓頁面看起來載入地更快。這是因為把樣式表放在head裡能讓頁面逐步渲染。
關注效能的前端工程師想讓頁面逐步渲染。也就是說,我們想讓瀏覽器盡快顯示已有內容,這在頁面上有一大堆內容或用戶網速很慢時顯得尤為重要。給使用者顯示回饋(例如進度指標)的重要性已經被廣泛研究過,並且被記錄下來了。在我們的例子中,HTML頁面就是進度指標!當瀏覽器逐漸載入頁面頭部,導航條,頂部logo等等內容的時候,這些都被正在等待頁面載入的使用者當作回饋,能夠提高整體使用者體驗。
js部分15.去除重複腳本頁面含有重複的腳本檔案會影響效能,這可能和你想像的不一樣。在美國前10大web站點的評審中,發現只有2個站點含有重複腳本。兩個主要原因增加了在單一頁面中出現重複腳本的幾率:團隊大小和腳本數量。在這種情況下,重複腳本會建立不必要的HTTP請求,執行無用的JavaScript程式碼,而影響頁面效能。
IE會產生不必要的HTTP請求,而Firefox不會。在IE中,如果一個不可快取的外部腳本被頁面引入了兩次,它會在頁面載入時產生兩個HTTP請求。即使腳本是可快取的,在使用者重新載入頁面時也會產生額外的HTTP請求。
除了產生沒有意義的HTTP請求之外,多次對腳本求值也會浪費時間。因為無論腳本是否可緩存,在Firefox和IE中都會執行冗餘的JavaScript程式碼。
避免不小心把相同腳本引入兩次的一種方法就是在模版系統中實現腳本管理模組。典型的腳本引進方法就是在HTML頁面中用SCRIPT標籤:
<script type=text/javascript src=menu_1.0.17.js></script>16.盡量減少DOM訪問
用JavaScript存取DOM元素是很慢的,所以,為了讓頁面反應更迅速,應該:
有時候感覺頁面反映不夠靈敏,是因為有太多頻繁執行的事件處理器被添加到了DOM樹的不同元素上,這就是推薦使用事件委託的原因。如果一個div裡面有10個按鈕,應該只為div容器增加一個事件處理器,而不是每個按鈕都新增一個。事件能夠冒泡,所以可以捕捉事件並得知哪個按鈕是事件來源。
18.把腳本放在底部腳本會阻塞並行下載,HTTP/1.1官方文件建議瀏覽器每個主機名下並行下載的元件數不要超過兩個,如果圖片來自多個主機名,並行下載的數量就可以超過兩個。如果腳本正在下載,瀏覽器就不會開始任何其它下載任務,即使是在不同主機名稱下的。
有時候,並不容易把腳本移到底部。舉個例子,如果腳本是用document.write插入到頁面內容中的,就沒辦法再往下移了。也可能有作用域問題,在多數情況下,這些問題都是可以解決的。
一個常見的建議是用延遲(deferred)腳本,有DEFER屬性的腳本意味著不能含有document.write,並且提示瀏覽器告訴他們可以繼續渲染。不幸的是,Firefox不支援DEFER屬性。在IE中,腳本可能被推遲,但不盡人意。如果腳本可以推遲,我們就可以把它放到頁面底部,頁面就可以更快地載入。
javascript, css 19.把JavaScript和CSS放到外面很多效能原則都是關於如何管理外部元件的,然而,在這些顧慮出現之前你應該問一個更基礎的問題:應該把JavaScript和CSS放到外部文件中還是直接寫在頁面裡?
實際上,用外部檔案可以讓頁面更快,因為JavaScript和CSS檔案會被快取在瀏覽器中。 HTML文件中的行內JavaScript和CSS在每次請求該HTML文件的時候都會重新下載。這樣做減少了所需的HTTP請求數,但增加了HTML文件的大小。另一方面,如果JavaScript和CSS在外部文件中,並且已經被瀏覽器快取起來了,那麼我們就成功地把HTML文檔變小了,而且還沒有增加HTTP請求數。
20.壓縮JavaScript和CSS壓縮具體來說就是從程式碼中移除不必要的字元以減少大小,從而提升載入速度。程式碼最小化就是去掉所有註解和不必要的空白字元(空格,換行和tab)。在JavaScript中這樣做能夠提高回應效能,因為要下載的檔案變小了。兩個最常用的JavaScript程式碼壓縮工具是JSMin和YUI Compressor,YUI compressor還可以壓縮CSS。
混淆是一種可選的源碼最佳化措施,要比壓縮更複雜,所以混淆過程也更容易產生bug。在美國前十名的網站調查中,壓縮可以縮小21%,而混淆能縮小25%。雖然混淆的縮小程度更高,但比壓縮風險更大。
除了壓縮外部腳本和樣式,行內的<script>和<style>區塊也可以壓縮。即使啟用了gzip模組,先進行壓縮也能夠縮小5%或更多的大小。 JavaScript和CSS的用處越來越多,所以壓縮程式碼會有不錯的效果。
圖片21.優化圖片試著把GIF格式轉換成PNG格式,看看是否要節省空間。在所有的PNG圖片上執行pngcrush(或其它PNG最佳化工具)
22.優化CSS Sprite不要因為在HTML中可以設定寬高而使用本不需要的大圖。如果需要
<img width=100 height=100 src=mycat.jpg Host: us.yimg.com If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT If-None-Match: 10c24bc-4ab-457 1.1 304 Not Modified32.對Ajax用GET請求
Yahoo!郵箱團隊發現使用XMLHttpRequest時,瀏覽器的POST請求是透過一個兩步驟的程序來實現的:先發送HTTP頭,在發送資料。所以最好用GET請求,它只需要發送一個TCP封包(除非cookie特別多)。 IE的URL長度最大值是2K,所以如果要傳送的資料超過2K就無法使用GET了。
POST請求的一個有趣的副作用是實際上沒有發送任何數據,就像GET請求一樣。如同HTTP說明文件中所描述的,GET請求是用來檢索資訊的。所以它的語意只是用GET請求來請求數據,而不是用來傳送需要儲存到伺服器的資料。
33.儘早清空緩衝區當使用者要求一個頁面時,伺服器需要用大約200到500毫秒來組裝HTML頁面,在這段期間,瀏覽器閒等著資料到達。 PHP中有一個flush()函數,允許向瀏覽器發送一部分已經準備完畢的HTML響應,以便瀏覽器可以在後台準備剩餘部分的同時開始獲取組件,好處主要體現在很忙的後台或者很輕的前端頁面上(PS 也就是說,響應時耗主要在後台方面時最能體現優勢)。
較理想的清空緩衝區的位置是HEAD後面,因為HTML的HEAD部分通常更容易生成,並且允許引入任何CSS和JavaScript文件,這樣就可以讓瀏覽器在後台還在處理的時候就開始並行獲取組件。
例如:
... <!-- css, js --> </head> <?php flush(); ?> <body> ... <!-- content -->34.使用CDN(內容傳遞網路)
使用者與伺服器的實體距離對回應時間也有影響。把內容部署在多個地理位置分散的伺服器上能讓使用者更快載入頁面。但具體怎麼做呢?
實現內容在地理位置上分散的第一步是:不要嘗試去重新設計你的web應用程式來適應分散式結構。這取決於應用程序,改變結構可能包括一些令人望而生畏的任務,例如同步會話狀態和跨伺服器複製資料庫事務(翻譯可能不準確)。縮短使用者和內容之間距離的提議可能被推遲,或者根本不可能通過,就是因為這個難題。
記住終端用戶80%到90%的回應時間都花在下載頁面元件上了:圖片,樣式,腳本,Flash等等,這是業績黃金法則。最好先分散靜態內容,而不是一開始就重新設計應用程式結構。這不僅能夠大幅減少反應時間,也更容易表現出CDN的功勞。
內容傳遞網路(CDN)是一組分散在不同地理位置的web伺服器,用來給使用者更有效率地傳送內容。典型地,選擇用來發送內容的伺服器是基於網路距離的衡量標準的。例如:選跳數(hop)最少的或回應時間最快的伺服器。
35.添上Expires或Cache-Control HTTP頭這條規則有兩個面向:
網頁設計越來越豐富,這意味著頁面裡有更多的腳本,圖片和Flash。網站的新訪客可能還是必須提交幾個HTTP請求,但透過使用有效期能讓元件變得可緩存,這避免了在接下來的瀏覽過程中不必要的HTTP請求。有效期限HTTP頭通常被用在圖片上,但它們應該用在所有元件上,包括腳本、樣式和Flash元件。
瀏覽器(和代理程式)用快取來減少HTTP請求的數量和大小,讓頁面能夠更快載入。 web伺服器透過有效期限HTTP回應頭來告訴客戶端,頁面的各個元件應該被快取多久。用一個遙遠的將來時間做有效期,告訴瀏覽器這個回應在2010年4月15日前不會改變。
Expires: Thu, 15 Apr 2010 20:00:00 GMT
如果你用的是Apache伺服器,用ExpiresDefault指令來設定相對於目前日期的有效期限。以下的範例設定了從請求時間起10年的有效期限:
ExpiresDefault access plus 10 years
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。