日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

给你的站点全面提速——来自Yahoo UI的各种Bset Practices

發(fā)布時間:2024/4/17 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 给你的站点全面提速——来自Yahoo UI的各种Bset Practices 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最少化Http請求

終端用戶80%的響應時間都花在前端(而非服務端處理)。而這其中絕大部分的時間又都花在下載所有的頁面“組件”:圖片、樣式表文件、腳本文件、Flash等。而按需加載,減少http的請求數(shù)來呈現(xiàn)頁面,是加快頁面呈現(xiàn)的關鍵。

而減少頁面組件的其中一種方式就是簡化頁面設計。但有一種既呈現(xiàn)富客戶端組件,同時又使頁面的響應時間得以加快嗎?這里有幾種技術能夠有效減少http的請求數(shù),并且又能夠支持富客戶端頁面的設計。

合并文件:你可以合并多個文件來減少http請求,比如合并腳本文件,簡化并合并多個樣式文件。當那些腳本或樣式文件對各個頁面都不盡相同時,這將變得更具挑戰(zhàn),但是把它列入你發(fā)布的其中一個步驟吧!

合并圖片:這可以有效地減少你對于圖片的請求。合并你的背景圖片到一個大圖片中,并使用CSS的background-image和background-position屬性來呈現(xiàn)你最終想要的圖片區(qū)域。

Image maps,合并多個圖片到一個大圖片中。圖片的總體大小和原來相同,但減少了http請求的數(shù)量從而可以為網(wǎng)頁加速。Image maps僅僅在圖片位于頁面中相鄰的區(qū)域的情況下,才會起作用,例如實現(xiàn)一個導航條。定義image maps的坐標很乏味且容易出錯。使用Image maps的導航也不可訪問,所以不做過多推薦。

內(nèi)聯(lián)圖片:使用data:URL scheme來嵌入圖片的數(shù)據(jù)到最終的頁面(曾Google有對圖片這個做過)。這會導致你HTML文檔的大小變大。合并內(nèi)聯(lián)圖片到你(緩存過)的樣式文件中是一種減少HTTP請求以及避免增加你頁面大小的方式。內(nèi)聯(lián)圖片的方式并不為所有現(xiàn)代主流瀏覽器所主持!

為首次訪問的用戶提高性能,這是一個非常重要的指引。據(jù)統(tǒng)計,40%-60%日常用戶訪問你的站點的時候,處于一個“零緩存”的狀態(tài)。所以,確保你的頁面對那些首次訪問的訪問者來說是快速的,這是一個非常重要的用戶體驗。

?

使用CDN(ContentDelivery Network)

用戶接近你的web服務器對于響應時間是有影響的。將你的靜態(tài)內(nèi)容分散到多個不同地理區(qū)域的服務器上,從用戶的角度來看將會覺得你的頁面加載地更迅速。但你應該從哪兒開始呢?

首先作為第一步,你應該實現(xiàn)對內(nèi)容的地理分散,不要企圖從新設計你的web應用程序來滿足一種“分布式架構”。依賴應用程序,改變架構可能包含著繁重的任務,比如同步Session狀態(tài)、跨服務器區(qū)域來復制數(shù)據(jù)庫事務。企圖減少用戶和你內(nèi)容的距離可能會被這種應用架構步驟延遲或者,從來都通不過。

終端用戶80%的響應時間都花在前端(而非服務端處理)。而這其中絕大部分的時間又都花在下載所有的頁面“組件”:圖片、樣式表文件、腳本文件、Flash等。這是黃金法則。而不是開始去進行對你系統(tǒng)架構的重新設計等困難的工作。最好先分散你的靜態(tài)內(nèi)容。這不僅會讓響應時間大幅減少,而且也使得內(nèi)容分發(fā)網(wǎng)絡變得更加容易。

CDN是一組web服務器的集合,它跨越多個對用戶更有效的內(nèi)容分發(fā)位置。服務器對一個特別用戶進行內(nèi)容分發(fā)一般都是基于衡量網(wǎng)絡的接近程度。例如,花費最少的網(wǎng)絡帶寬或者以最快的時間響應的服務器將會基于策略被選中。

某些大型的互聯(lián)網(wǎng)公司都擁有其自身的CDN,但使用一個CDN服務提供商更具有經(jīng)濟效益。對于一個剛起步的公司或者一個死人站點, CDN服務的花費可能是難以接受的,但隨著你的目標用戶群的日趨龐大,甚至全球化,CDN對于加快響應將是必不可少的。在Yahoo,那些將靜態(tài)內(nèi)容移動到CDN上的web應用給終端用戶提升了20%甚至更多的響應時間。選擇CDN對代碼的改動是輕量級的,并且那將能夠動態(tài)地提高你站點的速度。

?

增加一個Expires或Cache-Control 頭

下面是該規(guī)則的兩個方面:

1、?對靜態(tài)組件:實現(xiàn)“永不過期”策略(通過設置一個更久遠的Expires頭)

2、?對動態(tài)組件:使用Cache-Control響應頭來幫助瀏覽器有條件地請求。

Web頁面設計正在走向富客戶端話,這意味著更多的腳本、樣式文件、圖片以及Flash將要放置在頁面上。而第一次訪問你頁面的用戶可能需要發(fā)出很多次的http請求,但使用Expires頭可以使某些頁面組件變得“可緩存”。這避免了對后續(xù)頁面視圖組件的不必要的請求。Expire頭最通常被用于圖片上,但他們應該被使用在所有的包括腳本、樣式文件以及Flash組件中。

瀏覽器(以及代理)使用緩存來減少http請求的次數(shù),使得網(wǎng)站頁面加載得更快。web服務器使用Expires的http響應頭來告訴客戶端某個組件應該被緩存多久。這是一個更長時間的Expires頭,告訴瀏覽器直到2010年4月15日該響應才會失效。

Expires: Thu, 15 Apr 2010 20:00:00 GMT
如果你的服務器是Apache,使用ExpiresDefault指令來設置一個相對當前日期的過期時間。下面的示例演示了使用ExpiresDefault來設置自請求時間起十天之后失效。

ExpiresDefault "access plus 10 years"

記住,如果你使用一個時間更長的Expires頭,那么無論何時你改變該組件的時候,你不得不改變該組件的名稱。在Yahoo,我們在該步驟,通常采用如下辦法——使用一個版本號嵌入到組件的名稱中,例如:yahoo_2.0.6.js

使用一個過期時間更長的Expires頭來影響頁面視圖,只是在用戶已經(jīng)訪問過你的站點后才會起作用。所以當用戶首次訪問或者瀏覽器沒有緩存的情況下,它對http請求數(shù)沒有產(chǎn)生作用。因此該方法對性能的提升依賴于用戶訪問你的一個擁有初期緩存頁面的頻度(初期緩存已經(jīng)包含了所有頁面部件的緩存)。通過使用一個更長時間的Expires頭,你可以增加被瀏覽器緩存組件的數(shù)量,并且可以重用后續(xù)頁面視圖而不需要完全請求整個頁面。


Gzip 組件

在網(wǎng)絡上傳輸http請求和響應的時間可以隨著前端工程師的正確決定而顯著減少。終端用戶的帶寬速度、Internet服務提供商、對等交換點的接近程度等等都超出了開發(fā)團隊的控制,這是事實。但仍然有很多其他對響應時間產(chǎn)生影響的因素。而壓縮通過減少http響應的大小來減少響應時間。

從HTTP1.1開始,web客戶端通過在Accept-Encoding請求頭來標識對壓縮的支持。

Accept-Encoding: gzip, deflate

如果Web服務器看到該請求頭,它可能會使用客戶端列出來的其中一種方法來壓縮響應。而web服務器通知客戶端的方式是在響應頭中標注Content-Encoding:

Content-Encoding: gzip

Gzip是當下最流行以及最有效的壓縮方式。它由GNU項目組開發(fā)并且被標準化到RFC 1952。你可能會看到的另一種壓縮格式deflate,但它缺失有效性,并且不是特別流行。

Gzip壓縮通常將輸出大小減小到原來的30%。現(xiàn)如今約90%的瀏覽器聲稱支持gzip壓縮。如果你使用Apache,配置gzip的module取決于你的版本,apache1.3使用mod_gzip而apache 2.x使用 mod_deflate。

有可以代理或者瀏覽器期望的內(nèi)容與壓縮過的內(nèi)容不匹配,成為一個眾所周知的問題。幸運的是,隨著舊版本瀏覽器的日漸淘汰,這些邊緣問題也正逐漸減少。而Apache能夠自動地幫助你加入Vary響應頭。

服務器選擇壓縮哪些文件是基于文件類型的,但通常對此都有太多的限制。大部分的web站點都gzip它們的html文檔。當然你的腳步以及樣式文件也是值得壓縮的,但許多web站點錯失了這么做的機會。事實上,任何文本形式的響應,包括XML,JSON都是值得壓縮的。而圖片與PDF文件不應該被gzip,因為它們已經(jīng)被壓縮過了。嘗試壓縮它們不僅浪費CPU,而且反而會增加文件大小。


將樣式表文件的引用放在頭部

在Yahoo的網(wǎng)站中,通過研究我們發(fā)現(xiàn),將樣式表的引用放到文檔的HEAD中能夠使頁面加載得更快。這是因為將樣式表的引用放在HEAD中,允許頁面逐步解析。

前端工程師很關系性能,他們希望頁面被逐步地加載。我們希望瀏覽器任何時候都可以盡可能快地“打印”頁面。這對那些擁有很多內(nèi)容的頁面以及那些網(wǎng)速很慢的用戶來講是特別重要的。給用戶視覺反饋,比如進度指示,是非常重要的。在這種情況下HTML頁面是一個進度指示器。當瀏覽器逐步地加載頭部、導航條、頭部的logo等。所有的這些都給正在等待頁面的用戶視覺反饋。這能夠提供一個更好地用戶體驗。

將對樣式表的引用放到html文檔的底部,這會阻止頁面在很多瀏覽器(包括IE)中的順序呈現(xiàn)。這些瀏覽器會阻塞頁面呈現(xiàn)來防止元素的樣式變化帶來的頁面重繪。這樣用戶在瀏覽的時候將會看到一個空白的頁面。

?

將腳本放置到底部

腳本產(chǎn)生的問題是,他們會阻塞并發(fā)的下載。HTTP1.1標準建議瀏覽器對每個主機頁面部件的并發(fā)下載數(shù)不超過兩個。如果你將你的圖片放在多個不同的域名下,那么就可以獲得同時不止兩個的并發(fā)下載次數(shù)。然而,腳本在下載的時候,瀏覽器卻不會開啟任何其他的下載,甚至來自其他域名的也不會。

在某些情況下,將腳本移動到尾部并不是那么容易。例如,腳本使用document.write來插入頁面內(nèi)容的某個部分,那么它就不能被移動到頁面的下面。這可能也是一個“域”的問題,當然有很多方式能夠解決這些問題。

經(jīng)常出現(xiàn)的一個替代的方案就是延遲腳本的執(zhí)行。而defer屬性表示腳本不包含document.write,它是一個線索——用來告訴瀏覽器,可以繼續(xù)渲染。不幸的是,FireFox不支持defer屬性。在IE中,腳本可能可以被“延遲”,但并不是盡可能地要求腳本這么做。如果一個腳本可以被延遲執(zhí)行,那么它也可以被移動到頁面的底部。那將能使你的頁面加載地更快。


避免CSS表達式

CSS表達式很強大(但同時也很危險)。它能夠動態(tài)地設置CSS屬性。自從IE5開始被支持,但是在IE8中又開始被廢棄。舉個例子,背景色可以被設置為每個小時改變一次的CSS表達式:

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

就像在這里展示的一樣,expression方法接受一個javascript表達式。CSS屬性被設置為Javascript表達式計算出的結果。Expression會被其他瀏覽器忽視,所以它只是在IE中需要設置一個持續(xù)變化的樣式時才變得很有用。

而采用表達式的問題是,它計算的結果更多時間里都超過了人們的預期。因為它們不僅在頁面呈現(xiàn)或者改變大小的時候被計算,甚至當頁面被上下滾動或者用戶的鼠標在頁面上移動的時候也會計算。給CSS表達式加入一個計數(shù)器,將會允許我們跟蹤什么時候或者怎樣使得CSS開始了它的計算。在一個頁面上移動鼠標可以很容易超過10000求值。

減少你CSS表達式求值次數(shù)的一種方式是使用一次表達式,表達式首次計算出結果的時候,將其設置到一個明確的值來替代CSS表達式。如果其在整個頁面的生存期內(nèi)必須動態(tài)地變化樣式,使用事件處理器來取代CSS表達式是一個很不錯的替代方案。如果你必須使用CSS表達式,記住他們可能會被計算成千上萬次,因而可能影響到你頁面的性能。


將Javascript與CSS搬到外部

很多關于提升性能的“準則”都在處理如何管理這些外部“組件”的問題。然而,在這之前,你需要先考慮一個最基本的問題:應該把Javascript與CSS包含到外部文件中嗎,或者內(nèi)聯(lián)在頁面本身?

總得來說,在現(xiàn)實中使用外部文件能夠使頁面加載地更快。這是因為javascript與CSS文件都被緩存在瀏覽器中。Javascript與CSS如果內(nèi)嵌在HTML文檔中,那么每次該文檔被請求時,這些js與css都會被再次下載。這能夠減少必要的http請求數(shù),但卻增大了文本本身的大小。在另一方面,如果javascript與css作為外部文件被緩存到瀏覽器或客戶端,html文檔的大小會減少同時也沒有增多HTTP請求數(shù)。

一個重要的因素是那些外部的JS文件與CSS文件組件被緩存的頻率也與HTML文檔的請求數(shù)有關。對于這個因素,雖然難以量化,但可以使用各種各樣的指標來衡量。如果你站點的用戶在一個會話中可以查看多個頁面視圖并且你的頁面中有很多重用的相同的腳本以及樣式文件。這就能明顯地體現(xiàn)從緩存外部文件中獲得的收益。

許多網(wǎng)站在這樣的指標中。對于這些網(wǎng)站而言,通常最好的解決方案是將Javascript與CSS文件作為外部文件。而對于這個原則,唯一例外的就是首頁,你可以對它采用內(nèi)聯(lián)的方式。首頁一般只有很少的(也許只有一個)頁面視圖,對一個會話而言,可能會發(fā)現(xiàn)內(nèi)聯(lián)javascript與CSS文件能夠導致終端用戶的響應時間變得更短。

通常對于許多頁面的第一個視圖,有許多技術能夠減少HTTP請求,比如內(nèi)聯(lián),或者通過分離到外部文件來從緩存獲益。


減少DNS查找

Domain Name System(DNS)映射主機名到IP地址,就像電話薄映射人名到他們的電話號碼一樣。當你在瀏覽器地址欄中輸入www.yahoo.com的時候,瀏覽器連接著的一個DNS解析器能夠返回服務器的IP地址。DNS需要一定的時間,通常需要花費20-120毫秒的時間來對一個給定的主機名進行IP地址查找。除非DNS查找地址完成,否則瀏覽器不能從該主機下載任何內(nèi)容。

DNS查找如果能夠被緩存,可以獲得更好的性能。這個緩存可以放在一個特殊的緩存服務器上,被用戶的ISP或者本地區(qū)域網(wǎng)絡來維護,但也有許多緩存發(fā)生在獨立的用戶計算機上。DNS信息被保存在操作系統(tǒng)的DNS緩存中(在Windows上是DNS客戶服務)。大部分的瀏覽器都有他們自己的緩存,用以區(qū)別操作系統(tǒng)的緩存。一旦瀏覽器將DNS記錄保存在它們自己的緩存中,它將不需要另外向操作系統(tǒng)請求記錄。

IE默認緩存DNS查找30分鐘,由DnsCacheTimeout注冊表設置指定。Firefox緩存DNS查找一分鐘,這是由network.dnsCacheExpiration配置設置的。

當客戶端的DNS緩存為空(這里指瀏覽器和操作系統(tǒng)都為空)的時候,DNS查找的次數(shù)就等于網(wǎng)頁上主機名唯一出現(xiàn)的次數(shù)。這其中就包含了頁面URL、images、腳本文件、樣式文件、Flash對象等,所使用的URL中的主機名。減少這些唯一URL主機名可以減少DNS的查找。

減少唯一主機名出現(xiàn)的次數(shù)能夠潛在地減少發(fā)生在頁面加載時的并發(fā)下載次數(shù)。避免DNS查找能夠減少頁面加載的時間,但減少并發(fā)加載的次數(shù)卻有可能增加響應的時間。我的一個觀點是,將這些組件分割為至少跨越兩個但是最多不超過四個主機。這能夠在兩者之間取得平衡。

?

壓縮Javascript與CSS

壓縮指的是從代碼中移除不必要的字符,來減少它的大小以加快響應。當所有不必要的東西(比如空白字符,空格,換行tab制表符等)被移除,文件就會變得很小。對于JS而言,這提高了響應時間,因為下載文件的大小小了很多。兩個很流行的壓縮JS的工具是JSMin和YUI Compressor YUIcompressor也能夠壓縮CSS。

混淆是一種能夠作用在源代碼上的可替代的操作。它比壓縮更為復雜,因而更容易產(chǎn)生錯誤的是混淆本身的步驟。對美國排名前十的網(wǎng)站的一項調查統(tǒng)計,壓縮占有21%對比混淆占有25%。盡管混淆有一個更大的壓縮比,但純粹壓縮的風險來得更小一些。

另外,壓縮額外的腳本和樣式,而內(nèi)斂到文檔中的<script>標簽塊以及<style>樣式快也能夠并且應該被壓縮。甚至如果你gzip你的腳本和樣式,它們的大小也能夠減少5%或者更多。隨著Javascript以及CSS使用和大小的增加,這將能夠給你提供更好的性能。

?

避免重定向

重定向都是使用301和302狀態(tài)碼完成的。這里是一個301響應的http頭部:

HTTP/1.1 301 Moved Permanently Location: http://example.com/newuri Content-Type: text/html

瀏覽器自動地引導用戶到Location字段所標示的特定URL頁面。重定向所需要的所有的信息都在該響應頭中。而響應的實體通常都是空的。盡管他們有名稱,301和302在實踐中都不會被緩存,除非額外的響應標識頭,比如Expires或者Cache-Control,來標識它們應該被緩存。而meta refresh標簽與Javascript是將用戶定向到其他頁面的兩種方式,但如果你必須做重定向,更好的技術實現(xiàn)是使用標準的3XX HTTP狀態(tài)碼,這主要是用來確保后退按鈕能夠正常工作。

最主要說明的一點事,重定向降低了用戶體驗。在用戶與HTML文檔插入一個重定向延遲了頁面上所有的東西,因為頁面沒有什么可以呈現(xiàn)并且沒有組建可以開始下載,知道HTML文檔到達。

其中一個最沒必要的重定向經(jīng)常會發(fā)生,并且web開發(fā)者通常也不會意識到它。它發(fā)生在當一個URL結尾需要以一個‘/’結束,但如果缺失的話,就會發(fā)生。例如,訪問http://astrology.yahoo.com/astrology導致了一個301響應,其中包含了一個對http://astrology.yahoo.com/astrology/的重定向(注意結尾加了)。在Apache中,通過使用alias或者mod_rewrite或者直接使用DirectorySlash就可以解決,如果你正在使用Apache處理器的話。

?

移除重復的腳本

在一個頁面中引入相同的Javascript文件兩次會損失性能。這不同于你想的那樣。對美國排名前十的網(wǎng)站的一項統(tǒng)計發(fā)現(xiàn),10個站點中有兩個站點包含有重復的腳本。有兩個主要的因素導致:團隊規(guī)模以及腳本文件的數(shù)目。當發(fā)生這樣的情況,重復的腳本文件引用會損失性能,因為,它們會創(chuàng)建不必要的HTTP請求并且會完成一些沒必要的執(zhí)行。

沒必要的HTTP請求會發(fā)生在IE中,但不會發(fā)生在Firefox中。在IE中,如果一個外部的腳本被引入兩次。并且沒有緩存,它會在頁面加載時產(chǎn)生兩個HTTP請求。就算腳本被緩存,額外的HTTP請求也會在用戶重新加載頁面的時候發(fā)生。

除了生成的“不必要”的HTTP請求外,時間也會被浪費在執(zhí)行這些腳本上。該冗余的JS執(zhí)行在IE與Firefox中都會發(fā)生,與這些腳本是否被緩存無關。

避免不小心包含相同的腳本兩次的一種方法是在你的模板系統(tǒng)中實現(xiàn)一個腳本關系模塊。傳統(tǒng)的包含腳本的一種方式是在你的HTML頁面中使用SCRIPT標簽。

<script type="text/javascript" src="menu_1.0.17.js"></script>

在PHP中,另一種替代方式是創(chuàng)建一個稱之為insertScript的函數(shù)。

<?php insertScript("menu.js") ?>

除了防止相同的腳本被引入多次外,該函數(shù)可以處理腳本的其他問題,比如依賴性檢查以及在腳本文件中加入版本號來支持Expires緩存頭。

?

配置Etags

Entity tags(ETags)是一種供web服務器與瀏覽器使用,來決定在瀏覽器緩存中的組件是否匹配源服務器組件的方案。(“Entity”在這里等同于另一個單詞“component”的含義:images,scripts,stylesheets等)。Etags被用來提供一種比last-modified 日期更為靈活的驗證entities的方案。一個Etag是一個唯一的字符串用來標識一個組件的特定的版本。唯一的格式約束是,字符串需要被引號引起來。源服務器通過采用Etag響應頭來標注組件的Etag。

HTTP/1.1 200 OK Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT ETag: "10c24bc-4ab-457e1c1f" Content-Length: 12195

之后,如果瀏覽器不得不驗證一個組件,它使用If-None-Match頭來將Etag的內(nèi)容傳遞回源服務器。如果ETag得以匹配,那么就會給出一個304的狀態(tài)碼返回以無需這12195字節(jié)的響應(在本例中)。

GET /i/yahoo.gif HTTP/1.1 Host: us.yimg.com If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT If-None-Match: "10c24bc-4ab-457e1c1f" HTTP/1.1 304 Not Modified

ETag的問題在于,它們通常都是使用區(qū)別于宿主該站點的特殊服務器的唯一屬性來構建。當一個瀏覽器從一個服務器上獲得源組件并且稍后嘗試在一個不同的服務器上來驗證該組件時,ETag 是得不到匹配的。一個很通常的解決方案是采用一個服務器的集群來處理請求。默認的,無論是Apache還是IIS,它們嵌入數(shù)據(jù)到ETag都大大降低了對多服務器站點測試成功的可能性。

對Apache 1.3與2.X來講,ETag的格式是inode-size-timestamp。盡管一個給定的文件可能位于跨多個服務器的相同的目錄下,并且他們的大小相同,權限,創(chuàng)建時間等都相同。但,它的inode卻因不同的服務器而已。

IIS 5.0與6.0對ETag有一個很簡單的處理方案。ETag在IIS上的格式為Filetimestamp:ChangeNumber。ChangeNumber是一個用來跟蹤對配置改變的計數(shù)器。所以,ChangeNumber在跨所有IIS服務器背后的網(wǎng)站上是不可能相同的。

所以導致的最終結果是,由Apache和IIS對基于相同的頁面組件生成的ETag,在不同的服務器上是不相同的。如果ETag不匹配,用戶就無法接受到一個為ETag設計的小而快的304響應。取而代之的是,它們將被響應以200狀態(tài)碼,同時伴隨著所有組件內(nèi)容作為響應。如果你只是將你的站點宿主在一個服務器上,那這將不會產(chǎn)生任何問題。但,如果你采用的是這種多服務器的部署方式,并且你采用的是Apache或者IIS的默認ETag配置,你的用戶將會獲得更慢的頁面響應,你的服務器也會隨之帶來更高負荷的負載。你正在使用的更高的帶寬以及那些代理,它們無法有效地緩存你的內(nèi)容。甚至盡管你的組件有一個時間更長的Expires頭,但任何時候,用戶點擊重新加載或者刷新按鈕,仍然會向服務器發(fā)出請求。

如果你沒有利用ETag提供的靈活的驗證模型的優(yōu)勢,最好就干脆移除ETag。Last-Modified頭的驗證機制是基于組件的時間戳。ETag的移除減少了HTTP響應頭部與后續(xù)的請求頭部的大小。這篇Microsoft Support文章介紹了如何移除ETag。對Apache服務器而言,你只需要在你的Apache配置文件中,簡單地加上下面這句:

FileETag none

使Aajx可緩存

Ajax引入的其中一個好處就是,它能夠對用戶提供即時反饋,因為它從終端服務器異步請求信息。然而,使用Ajax也不能夠保證用戶將不再次按動它手里的鼠標來等待異步的javascript與xml響應的返回。在許多應用中,用戶是否保持等待,取決于怎樣使用Ajax。例如,在一個基于web的郵件客戶端中,用戶將等待Ajax的請求結果,因為他們需要找到所有符合他們搜索要求的郵件。你需要記住——異步并不意味著“瞬間”。

對于提高性能,優(yōu)化Ajax響應是很重要的舉措。提高Ajax性能的最重要的方式是使響應可緩存,就像在上面討論的過期頭和緩存頭一樣。

讓我們來看一個例子。一個Web 2.0的郵件客戶端,可能會采用Ajax來自動載入用戶的地址簿。如果用戶在距離上一次他使用該郵件客戶端之后都沒有修改過地址簿的話,那么可以從之前的響應中來讀取地址簿(如果該響應預先被緩存過的情況下)。瀏覽器必須要記住,什么時候使用之前緩存過的地址簿,而什么時候引發(fā)一個新請求。可以在異步請求地址簿的URL上加入一個時間戳來標識用戶修改他地址簿的最后時間,例如,&t=1190241612。如果自從上一次下載之后,地址簿沒有被修改,時間戳將與之前的保持一致,這樣就可以從瀏覽器的緩存中直接讀取結果。而如果用戶已經(jīng)改變過它的地址簿,自從上一次讀取之后。那么最新的時間戳將能夠確保URL不與緩存的URL相匹配。

就算你的Ajax響應是動態(tài)創(chuàng)建的,并且只是針對單個用戶的,他們也能夠被緩存。這么做會讓你的Web 2.0應用變得更快。

?

盡早地刷新緩沖區(qū)

當用戶請求一個頁面,在終端服務“組裝”一個頁面,無論如何最起碼都需要200到500ms。在這段時間中,瀏覽器是閑置的,因為它在等待數(shù)據(jù)的到達。在PHP中,你有一個flush()函數(shù)。它允許你發(fā)送你部分已準備好的HTML響應到瀏覽器端,以在你的服務端還在忙于準備HTML頁面其他部分的時候讓瀏覽器能夠開始下載頁面的部件(js、css文件)。

放置flush()函數(shù)的一個好位置是在HEAD標簽的后面,因為HTML的HEAD很容易生成,并且它允許你包含對CSS文件以及Javascript文件的引用。這樣就是服務端仍然在處理,你也可以開始并行地下載這些頁面部件。

例如:

... <!-- css, js --> </head> <?php flush(); ?> <body> ... <!-- content -->

對Ajax使用GET請求

Yahoo Mail團隊發(fā)現(xiàn):當使用XMLHttpRequest時,POST在瀏覽器中被作為兩步來實現(xiàn):首先發(fā)送頭部,然后才發(fā)送數(shù)據(jù)。所以,我們最好使用GET請求,它只發(fā)送一次TCP包(除非你的cookies很大)。在IE中, URL的最大長度為2K,所以如果你發(fā)送超過2K的數(shù)據(jù),就不能使用GET。

?

后加載組件

你可以自己看看你的頁面,并且問你自己——為了呈現(xiàn)頁面,哪些是絕對需要用來做初始化的?這樣,剩余的內(nèi)容與組件都可以等到必須的組件加載完之后再加載。

Javascript是分割在onload事件之前和之后加載的理想“侯選人”。例如,如果你有Javascript代碼或者類庫用來實現(xiàn)拖拽和動畫效果,那它們就屬于可等待的,因為在頁面上“拖拽”元素發(fā)生在初始化呈現(xiàn)之后。可以找到的其他“候選”包括隱藏內(nèi)容等。

當性能目標內(nèi)聯(lián)著其他web開發(fā)的最佳實踐時也是很好的。在這種情況下,漸進增強的想法告訴我們,當瀏覽器支持Javascript時,這能夠提高用戶體驗,但你不得不確信,當Javascript無法執(zhí)行時,頁面也能夠正常工作。所以,在你已經(jīng)能夠確信頁面工作地很好以后,你可以加強一些后期加載,給你更多的性能提升,比如拖放動畫等。

?

預加載組件

預加載可能看起來和后加載相反,但它最終確實有一個不同的目標。通過預加載組件,你可以利用瀏覽器正空閑的時間優(yōu)勢,來請求你將要使用的部件(比如圖片、樣式文件或腳本文件)。采用這種方式,當用戶訪問下一個頁面,你可能已經(jīng)下載完大部分的頁面部件并緩存在了客戶端,這樣你的頁面將會加載地更快。

其實,這里有好幾種預加載的方式:

l? 無條件預加載—一旦開始加載,你就去加載某些額外的組件(也許暫時你還不需要用到)。查看一下google.com,可以作為一個示例,看看一個精靈圖片是如何被請求加載的。該精靈圖片其實在google.com的主頁并不需要,但最終肯定會在展示搜索結果的頁面中使用。

l? 有條件預加載—基于用戶的操作,你做出一些有根據(jù)的假設。在search.yahoo.com,當你在輸入框中開始輸入的時候,你將看到一些額外的組件是怎樣被加載的。

l? 有預計的預加載—在部署一個全新的設計之前可以利用預加載的優(yōu)勢。這經(jīng)常發(fā)生在一個新版本發(fā)布之后,你可能會聽到——新站點是如此的酷,但它卻比之前的老版本慢得多。其中部分原因是,用戶訪問你的老版本是在一個全緩存的環(huán)境下,但新版本完全沒有經(jīng)過緩存。你可以在老的站點中,預計性地在瀏覽器空閑的情況下加載一些新站點中需要的圖片或腳本文件。


減少DOM元素的個數(shù)

一個復雜的頁面意味著要下載更多的數(shù)據(jù),也意味著Javascript對DOM的訪問會更慢。如果你在頁面循環(huán)500或者5000個DOM元素,當你給它們加入事件處理器時,它們確實會產(chǎn)生不同。

很多DOM元素可能會產(chǎn)生一些問題——有些應該提升頁面的標記而不是必要地刪除內(nèi)容。你是否使用嵌套的table來布局?你是否為了解決布局上的問題,向頁面上堆積更多的<div>?很可能有更好地或者在語義上來講更正確的方式來處理你的標簽。

YUI CSS ulities對于你的布局能夠提供很大的幫助:grid.css能夠幫助你均衡布局,fonts.css與reset.css幫你從瀏覽器特性的苦海中解脫出來。這是一次重新開始思考布局的機會,例如使用<div>只是在當語義上確實需要使用的時候,而不是因為它能夠呈現(xiàn)一個新行。

DOM元素的數(shù)目很容易測試,只需要在Firebug的命令行中敲入:

Document.getElementByTagName(‘*’).length

但,多少DOM元素才算太多呢?查看其他的一些簡單頁面,他們有好的標簽結構。例如:Yahoo! Home Page是一個相當“重量級” 的頁面,但仍然在七百個元素之內(nèi)(HTML 標簽)。

?

跨域分割組件

分割組件允許最大化地并發(fā)下載。確信你同時使用不超過24個域。例如,你可能將你的HTML文檔以及動態(tài)內(nèi)容持有在www.example.org上,然后可以將靜態(tài)內(nèi)容分割到static1.example.org和static2.example.org上。

想獲得更多信息,請查看MaximizingParallel Downloads in the Carpool Lane

?

最小化iframes的數(shù)目

Iframe允許一個HTML文檔被插入到父文檔中。理解iframe如何工作很重要,因為這有助于你有效地使用它:

<iframe>優(yōu)點:

l? 幫助放慢第三方內(nèi)容比如徽章和廣告

l? 安全沙盒

l? 并發(fā)下載腳本

?

<iframe>劣勢:

l? 即便是空白頁面也很“昂貴”

l? 阻塞頁面的加載

l? 沒有語義

?

沒有404

HTTP 請求很“昂貴”,所以發(fā)起一個HTTP請求并獲得一個沒有用的響應(例如404 Not Found)總是沒有必要的,并且將拖慢用戶的響應時間卻沒有任何好處。

某些站點有幫助性的404——你想XXX?這很好地提高了用戶體驗,但也浪費了服務端資源(比如數(shù)據(jù)庫等)。特別糟糕的是,當一個鏈接到外部Javascript的鏈接是錯誤的并且結果導致了404。首先,該下載將阻塞并行的其他下載,接著如果他是javascript文檔,瀏覽器可能會嘗試轉換404響應體,來嘗試發(fā)現(xiàn)一些有用的內(nèi)容。

?

減少Cookie的大小

HTTP Cookies 通常用于驗證,例如權限和個性化。c在往返于web服務器和瀏覽器的HTTP 頭中,ookies的信息會被交換。保持cookies盡量小很重要,因為它影響用戶的響應時間。

想獲得更多的信息,請訪問When theCookie Crumbles。記住這些結論:

l? 限制不必要的cookies

l? 保持cookies盡量小很重要,因為它影響用戶的響應時間

l? 要注意,在適當?shù)挠蚣墑e上設置Cookie,而不對其他子域產(chǎn)生影響

l? 設置一個適當?shù)倪^期日期。一個較早的過期時間或者在不久之后刪除cookie將會提高用戶的響應時間。

?

為頁面組件使用無Cookie的域名

當瀏覽器對靜態(tài)文件發(fā)送一次請求的同時也攜帶了cookies,而對服務端而言,這些cookies是無用的。所以他們只是增加了網(wǎng)絡流量。你應該確保將靜態(tài)組件作為無cookie的請求發(fā)送。創(chuàng)建一個子域并且將你所有的靜態(tài)組件放在子域里面。

如果你的域名為www.example.org,你可以將你的靜態(tài)組件放在static.example.org上。然而,如果如果你已經(jīng)在相對于www.example.org來講的頂級域:example.org上設置了cookies,那么所有static.example.org上將包含那些cookies。在這種情況下,你可以購買一個完整的新域名,來放置你的靜態(tài)文件,并使該域名無cookie。Yahoo!使用的是yimg.com,YouTube使用ytimg.com,Amazon使用images-amazon.com等。

在一個無cookie的域名上放置靜態(tài)組件的另一個好處是,有些代理可能會拒絕緩存那些帶有cookies的組件。如果你想,你應該對你的主頁使用example.org或者www.example.org。省略www讓你別無選擇,只能將cookies寫到*.example.org,所以,從性能的角度出發(fā),最好使用www.subdomain,將cookie寫到該子域上。

?

最少化DOM訪問

使用JS訪問DOM元素很慢,所以為了讓頁面有一個更為快速的響應,你應該:

l? 取消對已訪問元素的引用

l? 更新“離線”的節(jié)點,然后將他們加入樹中

l? 避免用JS處理布局問題

想獲得更多的信息,請閱讀?"High Performance Ajax Applications"

?

開發(fā)靈巧的事件處理器

有時頁面響應不夠迅速,是因為太多的事件處理器掛接在不同的DOM樹的元素上,他們會很頻繁地執(zhí)行。這就是為什么使用事件代理是一個很好的解決方案。如果你有10個按鈕在一個div中,附加僅僅一個事件處理器給div包裝器,而不是為每個按鈕都制定一個處理器。事件冒泡機制將能夠使你捕獲到事件以及它起源于哪個按鈕。

為了在DOM樹完成的時候做某些事情,你也不需要等待onload事件。經(jīng)常,所有你需要的指示你想訪問的元素在DOM樹結構中可以被訪問。你不需要等待所有的圖片被下載完成。DOMContentLoaded是一個你可能值得考慮用來替代onload的事件,但知道它在所有瀏覽器中可采用之前,你可以使用YUI Event utility,它有一個onAvilable函數(shù)。

為了獲得更多的信息,你可以閱讀這篇文章——"HighPerformance Ajax Applications"

?

選擇<link>而不是@import

之前的最佳實踐中,其中有一條是——CSS應該在文檔的頭部,這樣可以實現(xiàn)逐步呈現(xiàn)。

在IE中@import和在頁面的底部使用<link>的行為相同。所以,最好不要使用它。

?

避免篩選器

IE專有的AlphaImageLoader篩選器是用來修復在IE版本小于7的瀏覽器中半透明的PNG真彩色問題。該問題使用這個篩選器,當圖片正在被下載的時候,可以用來阻塞圖片的呈現(xiàn)并釋放瀏覽器。它也增加了內(nèi)存的開銷并且被應用到每個元素上面,不是每個圖片,是每個元素。所以,該問題是多方面的。

最好的方案是完全避免對AlphaImageLoader的使用。用PNG8取而代之,他們在IE中表現(xiàn)地很好。如果你一定要用AlphaImageLoader,使用帶下劃線的hack手段——_filter,這就避免了該方法對你的IE7+用戶的“懲罰”。

?

優(yōu)化圖片

在前端設計師為你的頁面創(chuàng)建完圖片之后,在你向你的web服務器請求這些圖片的時候

,這里仍然有些事情值得你嘗試。

l? 你可以查看GIF圖片,并且看是否他們用的是調色板的大小對應圖像中的顏色數(shù)量。使用Imagemagick,可以很容易地查看使用identify–verbose image.gif

當你看到一個圖片使用四個顏色以及一個250位顏色的“插槽”在調色板中,那就表示還有提升的空間。

l? 嘗試將GIF圖片格式轉為PNG格式,看是否大小有所減小。大部分情況下,答案都是肯定的。開發(fā)者通常都很不情愿使用PNG格式的圖片(由于瀏覽器支持受限的問題),但這在現(xiàn)在來講已經(jīng)是一個過去時了。唯一真正的問題是真彩色的PNG中的Alpha透明度問題,但同樣如此,GIF也不是真彩色,并且也不支持變量的透明度。所以任何一個GIF能夠做到的,一個調色板PNG(PNG8)也能夠做到(除了動畫)。該簡單的imagemagick命令會完成對一個GIF圖片到PNG格式圖片的“安全”轉換:

Convertimage.gif image.png

“所有我想說的就是——給PNG一次機會”

l? 為你所有的PNG圖片運行pngcrush(或者任何其他PNG優(yōu)化工具)。例如:

Pngcrushimage.png –rem alla –reduce –brute result.pgn

l? 給你的JPEG圖片運行jpegtran。該工具能夠對JPEG完成無損優(yōu)化,例如旋轉等,也能夠用來優(yōu)化以及移除內(nèi)容或者其他沒有用的信息(例如EXIF 信息)。

?

優(yōu)化CSS精靈

l? 在精靈中水平地呈現(xiàn)圖片,而不是垂直地呈現(xiàn),將能夠使文件更小。

l? 在精靈中合并相似的顏色可以使得對顏色計算的消耗降得更低,例如256位的顏色就很適合PNG8。

l? “變得對移動設備友好”并且不要在精靈中產(chǎn)生很大的差距。這不會體現(xiàn)在文件的大小上,但這能夠使得需要的內(nèi)存減少掉為用戶代理來比較圖片像素的開銷。100X100的圖片是1萬個像素,而1000X1000就是1百萬個像素。

?

不要在HTML中延展圖片

不要使用一個比你需要的尺寸更大的圖片,僅僅因為你覺得你可以在HTML中設置寬度和高度。如果你需要

<img width=”100” height=”100” src=”mycat.jpg”alt=”My Cat” />

然后你的圖片就應該是差不多100*100而不是一個延展到500*500大小的圖片。

?

確保favicon.ico很小并且可緩存

Favicon.ico是一個放置在你服務器根目錄下的一個圖片。它是必須的,因為如果沒有它,瀏覽器將會一直請求它。所以,最好不要響應以一個404 Not Found。同時,既然在相同的服務器上,在每次請求它的時候cookies都會發(fā)送。該圖片也會干擾下載順序,例如在IE中,當你在加載的時候請求一個額外的組件,favicon將會再這些額外的組件之前被加載。

因此,盡量減少favicon.ico帶來的弊端:

l? 確保它很小,最好小于1K

l? 設置一個你覺得合適的Expires頭。你可以安全地設置Expires頭在未來的幾個月過期。


保持組件在25K以下

該組件的限制是由于,有這樣一個事實——iPhone不會緩存超過25K的組件。注意,這是指未壓縮的大小。這樣只采用gzip壓縮可能不是很有效。

?

打包組件到一個文檔中

打包組件到一個文檔中就像一個帶有附件的email一樣,它幫助你在一個http請求中獲取幾個組件(記住,HTTP請求是很昂貴的)。當你使用此技術之前,首先核查一下用戶代理是否支持它(iPhone 不支持)。

?

避免錯誤的圖片引用

Image標簽的空src屬性將帶來不可預期的行為。它有兩種表現(xiàn)形式:

1、? 純粹的HTML:

<imgsrc=””>

2、? Javascript

Var img =newImage();

Img.src=””;

?

這兩種形式都會有相同的影響:瀏覽器將向你的服務器發(fā)送另一個請求。

l?Internet Explorer:向當前頁面所屬的文件夾發(fā)送一個請求

l?Safari 以及 Chrome:向最終頁面本身

l?FireFox 3以及早期版本的行為和Safari 以及 Chrome行為一致,但3.5版本解決了該問題【bug 444931】并且不再發(fā)送請求

l?Opera 不做任何事情

?

為什么該做法很不好?

1、? 通過發(fā)送大量不可預期的通信來削弱你服務器的性能,特別是那些每天被訪問幾百萬此的頁面更是這樣。

2、? 浪費服務器的計算周期來生成一個將不會被顯示的頁面。

3、? 可能破壞數(shù)據(jù)。如果你跟蹤請求的狀態(tài),要么通過cookies要么以另一種方式,你將有可能看到破空數(shù)據(jù)。盡管圖片請求不返回一個圖片,但所有的響應頭被讀取并且被瀏覽器接受,包含所有的cookies。雖然響應的其余部分被廢棄,但損害可能已經(jīng)發(fā)生。

導致該行為的問題是,在瀏覽器中解析URI的方式不盡相同。該行為被定義在RFC 3986-統(tǒng)一資源標識。當一個空字符串被當做一個URI,它被認為是一個相對URI,并且根據(jù)定義在5.2節(jié)的算法被解析。該特殊的例子——一個空字符串,被列在5.4節(jié)。

Firefox, Safari, and Chrome都能夠按照標準正確地解析空字符串,但IE并沒有正確地解析,而是選擇了遵循規(guī)范的早期版本——RFC 2396(它已經(jīng)過時,并被3986替代)。所以,從技術角度來講,瀏覽器將以它們自身支持的方式來解析相對URI。該問題在這個上下文中,主要想說明空字符串是無意義的。

HTML 5增加了src屬性的描述,指示瀏覽器不作出第4.8.2節(jié)中的額外要求:

Src屬性必須被標識,必須包含一個驗證過的URL并引用一個非交互的可選動畫、既不是頁面也不是腳本的圖片資源。如果元素基本的URI與文檔的路徑相同,這樣src屬性的值必須為非空的字符串。

值得期待的是,瀏覽器將不會存在這個問題。可能仍然需要一段時間來適應確保瀏覽器不小心執(zhí)行了該行為。



轉載于:https://www.cnblogs.com/wdpp/archive/2012/02/09/2386579.html

總結

以上是生活随笔為你收集整理的给你的站点全面提速——来自Yahoo UI的各种Bset Practices的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。