新聞資(zī)訊

網站頁面性能優化的20條黃金守則

1、用<link>代替@import

前面的最佳實現中(zhōng)提到CSS應該放(fàng)置在頂端以利于有序加載呈現。      

在IE中(zhōng),頁面底部@import和使用

作用是一(yī)樣的,因此最好不要使用它。


2、避免使用濾鏡      

IE獨有屬性AlphaImageLoader用于修正7.0以下(xià)版本中(zhōng)顯示PNG圖片的半透明效果。這個濾鏡的問題在于浏覽器加載圖片時它會終止内容的呈現并且凍結浏覽器。在每一(yī)個元素(不僅僅是圖片)它都會運算一(yī)次,增加了内存開(kāi)支,因此它的問題是多方面的。      

完全避免使用AlphaImageLoader的最好方法就是使用PNG8格式來代替,這種格式能在IE中(zhōng)很好地工(gōng)作。如果你确實需要使用AlphaImageLoader,請使用下(xià)劃線_filter又(yòu)使之對IE7以上版本的用戶無效。


3、把腳本置于頁面底部      

腳本帶來的問題就是它阻止了頁面的平行下(xià)載。HTTP/1.1 規範建議,浏覽器每個主機名的并行下(xià)載内容不超過兩個。如果你的圖片放(fàng)在多個主機名上,你可以在每個并行下(xià)載中(zhōng)同時下(xià)載2個以上的文件。但是當下(xià)載腳本時,浏覽器就不會同時下(xià)載其它文件了,即便是主機名不相同。      

在某些情況下(xià)把腳本移到頁面底部可能不太容易。比如說,如果腳本中(zhōng)使用了document.write來插入頁面内容,它就不能被往下(xià)移動了。這裏可能還會有作用域的問題。很多情況下(xià),都會遇到這方面的問題。      

一(yī)個經常用到的替代方法就是使用延遲腳本。DEFER屬性表明腳本中(zhōng)沒有包含document.write,它告訴浏覽器繼續顯示。不幸的是,Firefox并不支持DEFER屬性。在Internet Explorer中(zhōng),腳本可能會被延遲但效果也不會像我(wǒ)(wǒ)們所期望的那樣。如果腳本可以被延遲,那麽它就可以移到頁面的底部。這會讓你的頁面加載的快一(yī)點。


4、剔除重複腳本      

在同一(yī)個頁面中(zhōng)重複引用JavaScript文件會影響頁面的性能。你可能會認爲這種情況并不多見。對于美國前10大(dà)網站的調查顯示其中(zhōng)有兩家存在重複引用腳本的情況。有兩種主要因素導緻一(yī)個腳本被重複引用的奇怪現象發生(shēng):團隊規模和腳本數量。如果真的存在這種情況,重複腳本會引起不必要的HTTP請求和無用的JavaScript運算,這降低了網站性能。      

在Internet Explorer中(zhōng)會産生(shēng)不必要的HTTP請求,而在Firefox卻不會。在Internet Explorer中(zhōng),如果一(yī)個腳本被引用兩次而且它又(yòu)不可緩存,它就會在頁面加載過程中(zhōng)産生(shēng)兩次HTTP請求。即時腳本可以緩存,當用戶重載頁面時也會産生(shēng)額外(wài)的HTTP請求。      

除增加額外(wài)的HTTP請求外(wài),多次運算腳本也會浪費(fèi)時間。在Internet Explorer和Firefox中(zhōng)不管腳本是否可緩存,它們都存在重複運算JavaScript的問題。      

一(yī)個避免偶爾發生(shēng)的兩次引用同一(yī)腳本的方法是在模闆中(zhōng)使用腳本管理模塊引用腳本。在HTML頁面中(zhōng)使用

标簽引用腳本的最常見方法就是:      

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

在PHP中(zhōng)可以通過創建名爲insertScript的方法來替代:      

爲了防止多次重複引用腳本,這個方法中(zhōng)還應該使用其它機制來處理腳本,如檢查所屬目錄和爲腳本文件名中(zhōng)增加版本号以用于Expire文件頭等。


5、減少DOM訪問      

使用JavaScript訪問DOM元素比較慢(màn),因此爲了獲得更多的應該頁面,應該做到:緩存已經訪問過的有關元素 線下(xià)更新完節點之後再将它們添加到文檔樹(shù)中(zhōng) 避免使用JavaScript來修改頁面布局      

有關此方面的更多信息請查看Julien Lecomte在YUI專題中(zhōng)的文章“高性能Ajax應該程序”。


6、開(kāi)發智能事件處理程序      

有時候我(wǒ)(wǒ)們會感覺到頁面反應遲鈍,這是因爲DOM樹(shù)元素中(zhōng)附加了過多的事件句柄并且些事件句病被頻(pín)繁地觸發。這就是爲什麽說使用event delegation(事件代理)是一(yī)種好方法了。如果你在一(yī)個div中(zhōng)有10個按鈕,你隻需要在div上附加一(yī)次事件句柄就可以了,而不用去(qù)爲每一(yī)個按鈕增加一(yī)個句柄。事件冒泡時你可以捕捉到事件并判斷出是哪個事件發出的。      

你同樣也不用爲了操作DOM樹(shù)而等待onload事件的發生(shēng)。你需要做的就是等待樹(shù)結構中(zhōng)你要訪問的元素出現。你也不用等待所有圖像都加載完畢。      

你可能會希望用DOMContentLoaded事件來代替onload,但是在所有浏覽器都支持它之前你可使用YUI 事件應用程序中(zhōng)的onAvailable方法。


7、減小(xiǎo)Cookie體(tǐ)積      

HTTP coockie可以用于權限驗證和個性化身份等多種用途。coockie内的有關信息是通過HTTP文件頭來在web服務器和浏覽器之間進行交流的。因此保持coockie盡可能的小(xiǎo)以減少用戶的響應時間十分(fēn)重要。 有關更多信息可以查看Tenni Theurer和Patty Chi的文章“When the Cookie Crumbles”。這們研究中(zhōng)主要包括:去(qù)除不必要的coockie 使coockie體(tǐ)積盡量小(xiǎo)以減少對用戶響應的影響 注意在适應級别的域名上設置coockie以便使子域名不受影響 設置合理的過期時間。較早地Expire時間和不要過早去(qù)清除coockie,都會改善用戶的響應時間。


8、對于頁面内容使用無coockie域名      

當浏覽器在請求中(zhōng)同時請求一(yī)張靜态的圖片和發送coockie時,服務器對于這些coockie不會做任何地使用。因此他們隻是因爲某些負面因素而創建的網絡傳輸。所有你應該确定對于靜态内容的請求是無coockie的請求。創建一(yī)個子域名并用他來存放(fàng)所有靜态内容。      

如果你的域名是www.example.org,你可以在static.example.org上存在靜态内容。但是,如果你不是在www.example.org上而是在頂級域名example.org設置了coockie,那麽所有對于static.example.org的請求都包含coockie。在這種情況下(xià),你可以再重新購買一(yī)個新的域名來存在靜态内容,并且要保持這個域名是無coockie的。Yahoo!使用的是ymig.com,YouTube使用的是ytimg.com,Amazon使用的是images-anazon.com等等。      

使用無coockie域名存在靜态内容的另外(wài)一(yī)個好處就是一(yī)些代理(服務器)可能會拒絕對coockie的内容請求進行緩存。一(yī)個相關的建議就是,如果你想确定應該使用example.org還是www.example.org作爲你的一(yī)主頁,你要考慮到coockie帶來的影響。忽略掉www會使你除了把coockie設置到*.example.org(*是泛域名解析,代表了所有子域名譯者dudo注)外(wài)沒有其它選擇,因此出于性能方面的考慮最好是使用帶有www的子域名并且在它上面設置coockie。


9、優化圖像      

設計人員(yuán)完成對頁面的設計之後,不要急于将它們上傳到web服務器,這裏還需要做幾件事:你可以檢查一(yī)下(xià)你的GIF圖片中(zhōng)圖像顔色的數量是否和調色闆規格一(yī)緻。 使用imagemagick中(zhōng)下(xià)面的命令行很容易檢查: identify -verbose image.gif 如果你發現圖片中(zhōng)隻用到了4種顔色,而在調色闆的中(zhōng)顯示的256色的顔色槽,那麽這張圖片就還有壓縮的空間。

嘗試把GIF格式轉換成PNG格式,看看是否節省空間。大(dà)多數情況下(xià)是可以壓縮的。由于浏覽器支持有限,設計者們往往不太樂意使用PNG格式的圖片,不過這都是過去(qù)的事情了。現在隻有一(yī)個問題就是在真彩PNG格式中(zhōng)的alpha通道半透明問題,不過同樣的,GIF也不是真彩格式也不支持半透明。因此GIF能做到的,PNG(PNG8)同樣也能做到(除了動畫)。下(xià)面這條簡單的命令可以安全地把GIF格式轉換爲PNG格式: convert image.gif image.png “我(wǒ)(wǒ)們要說的是:給PNG一(yī)個施展身手的機會吧!” 在所有的PNG圖片上運行pngcrush(或者其它PNG優化工(gōng)具)。例如: pngcrush image.png -rem alla -reduce -brute result.png 在所有的JPEG圖片上運行jpegtran。這個工(gōng)具可以對圖片中(zhōng)的出現的鋸齒等做無損操作,同時它還可以用于優化和清除圖片中(zhōng)的注釋以及其它無用信息(如EXIF信息): jpegtran -copy none -optimize -perfect src.jpg dest.jpg


10、優化CSS不要出現404錯誤  

Spirite在Spirite中(zhōng)水平排列你的圖片,垂直排列會稍稍增加文件大(dà)小(xiǎo); Spirite中(zhōng)把顔色較近的組合在一(yī)起可以降低顔色數,理想狀況是低于256色以便适用PNG8格式; 便于移動,不要在Spirite的圖像中(zhōng)間留有較大(dà)空隙。這雖然不大(dà)會增加文件大(dà)小(xiǎo)但對于用戶代理來說它需要更少的内存來把圖片解壓爲像素地圖。100x100的圖片爲1萬像素,而1000x1000就是100萬像素。

HTTP請求時間消耗是很大(dà)的,因此使用HTTP請求來獲得一(yī)個沒有用處的響應(例如404沒有找到頁面)是完全沒有必要的,它隻會降低用戶體(tǐ)驗而不會有一(yī)點好處。      

有些站點把404錯誤響應頁面改爲“你是不是要找***”,這雖然改進了用戶體(tǐ)驗但是同樣也會浪費(fèi)服務器資(zī)源(如數據庫等)。最糟糕的情況是指向外(wài)部JavaScript的鏈接出現問題并返回404代碼。首先,這種加載會破壞并行加載;其次浏覽器會把試圖在返回的404響應内容中(zhōng)找到可能有用的部分(fēn)當作JavaScript代碼來執行。


11、使用内容分(fēn)發網絡      

用戶與你網站服務器的接近程度會影響響應時間的長短。把你的網站内容分(fēn)散到多個、處于不同地域位置的服務器上可以加快下(xià)載速度。但是首先我(wǒ)(wǒ)們應該做些什麽呢?      

按地域布置網站内容的第一(yī)步并不是要嘗試重新架構你的網站讓他們在分(fēn)發服務器上正常運行。根據應用的需求來改變網站結構,這可能會包括一(yī)些比較複雜(zá)的任務,如在服務器間同步Session狀态和合并數據庫更新等。要想縮短用戶和内容服務器的距離(lí),這些架構步驟可能是不可避免的。      

要記住,在終端用戶的響應時間中(zhōng)有80%到90%的響應時間用于下(xià)載圖像、樣式表、腳本、Flash等頁面内容。這就是網站性能黃金守則。和重新設計你的應用程序架構這樣比較困難的任務相比,首先來分(fēn)布靜态内容會更好一(yī)點。這不僅會縮短響應時間,而且對于内容分(fēn)發網絡來說它更容易實現。      

内容分(fēn)發網絡(Content Delivery Network,CDN)是由一(yī)系列分(fēn)散到各個不同地理位置上的Web服務器組成的,它提高了網站内容的傳輸速度。用于向用戶傳輸内容的服務器主要是根據和用戶在網絡上的靠近程度來指定的。例如,擁有最少網絡跳數(network hops)和響應速度最快的服務器會被選定。      

一(yī)些大(dà)型的網絡公司擁有自己的CDN,但是使用像Akamai Technologies,Mirror Image Internet, 或者Limelight Networks這樣的CDN服務成本卻非常高。對于剛剛起步的企業和個人網站來說,可能沒有使用CDN的成本預算,但是随着目标用戶群的不斷擴大(dà)和更加全球化,CDN就是實現快速響應所必需的了。以Yahoo來說,他們轉移到CDN上的網站程序靜态内容節省了終端用戶20%以上的響應時間。使用CDN是一(yī)個隻需要相對簡單地修改代碼實現顯著改善網站訪問速度的方法。


12、爲文件頭指定Expires或Cache-Control      

這條守則包括兩方面的内容: 對于靜态内容:設置文件頭過期時間Expires的值爲“Never expire”(永不過期) 對于動态内容:使用恰當的Cache-Control文件頭來幫助浏覽器進行有條件的請求      

網頁内容設計現在越來越豐富,這就意味着頁面中(zhōng)要包含更多的腳本、樣式表、圖片和Flash。第一(yī)次訪問你頁面的用戶就意味着進行多次的HTTP請求,但是通過使用Expires文件頭就可以使這樣内容具有緩存性。它避免了接下(xià)來的頁面訪問中(zhōng)不必要的HTTP請求。Expires文件頭經常用于圖像文件,但是應該在所有的内容都使用他,包括腳本、樣式表和Flash等。      

浏覽器(和代理)使用緩存來減少HTTP請求的大(dà)小(xiǎo)和次數以加快頁面訪問速度。Web服務器在HTTP響應中(zhōng)使用Expires文件頭來告訴客戶端内容需要緩存多長時間。下(xià)面這個例子是一(yī)個較長時間的Expires文件頭,它告訴浏覽器這個響應直到2010年4月15日才過期。      Expires: Thu, 15 Apr 2010 20:00:00 GMT      如果你使用的是Apache服務器,可以使用ExpiresDefault來設定相對當前日期的過期時間。下(xià)面這個例子是使用ExpiresDefault來設定請求時間後10年過期的文件頭:      

ExpiresDefault "access plus 10 years"      

要切記,如果使用了Expires文件頭,當頁面内容改變時就必須改變内容的文件名。依Yahoo!來說我(wǒ)(wǒ)們經常使用這樣的步驟:在内容的文件名中(zhōng)加上版本号,如yahoo_2.0.6.js。      

使用Expires文件頭隻有會在用戶已經訪問過你的網站後才會起作用。當用戶首次訪問你的網站時這對減少HTTP請求次數來說是無效的,因爲浏覽器的緩存是空的。因此這種方法對于你網站性能的改進情況要依據他們“預緩存”存在時對你頁面的點擊頻(pín)率(“預緩存”中(zhōng)已經包含了頁面中(zhōng)的所有内容)。Yahoo!建立了一(yī)套測量方法,我(wǒ)(wǒ)們發現所有的頁面浏覽量中(zhōng)有75~85%都有“預緩存”。通過使用Expires文件頭,增加了緩存在浏覽器中(zhōng)内容的數量,并且可以在用戶接下(xià)來的請求中(zhōng)再次使用這些内容,這甚至都不需要通過用戶發送一(yī)個字節的請求。


13、Gzip壓縮文件内容      

網絡傳輸中(zhōng)的HTTP請求和應答時間可以通過前端機制得到顯著改善。的确,終端用戶的帶寬、互聯網提供者、與對等交換點的靠近程度等都不是網站開(kāi)發者所能決定的。但是還有其他因素影響着響應時間。通過減小(xiǎo)HTTP響應的大(dà)小(xiǎo)可以節省HTTP響應時間。      

從HTTP/1.1開(kāi)始,web客戶端都默認支持HTTP請求中(zhōng)有Accept-Encoding文件頭的壓縮格式:Accept-Encoding: gzip, deflate      

如果web服務器在請求的文件頭中(zhōng)檢測到上面的代碼,就會以客戶端列出的方式壓縮響應内容。Web服務器把壓縮方式通過響應文件頭中(zhōng)的Content-Encoding來返回給浏覽器。    

Content-Encoding: gzip

Gzip是目前最流行也是最有效的壓縮方式。這是由GNU項目開(kāi)發并通過RFC 1952來标準化的。另外(wài)僅有的一(yī)個壓縮格式是deflate,但是它的使用範圍有限效果也稍稍遜色。

Gzip大(dà)概可以減少70%的響應規模。目前大(dà)約有90%通過浏覽器傳輸的互聯網交換支持gzip格式。如果你使用的是Apache,gzip模塊配置和你的版本有關:Apache 1.3使用mod_zip,而Apache 2.x使用moflate。      

浏覽器和代理都會存在這樣的問題:浏覽器期望收到的和實際接收到的内容會存在不匹配的現象。幸好,這種特殊情況随着舊(jiù)式浏覽器使用量的減少在減少。Apache模塊會通過自動添加适當的Vary響應文件頭來避免這種狀況的出現。      

服務器根據文件類型來選擇需要進行gzip壓縮的文件,但是這過于限制了可壓縮的文件。大(dà)多數web服務器會壓縮HTML文檔。對腳本和樣式表進行壓縮同樣也是值得做的事情,但是很多web服務器都沒有這個功能。實際上,壓縮任何一(yī)個文本類型的響應,包括XML和JSON,都值得的。圖像和PDF文件由于已經壓縮過了所以不能再進行gzip壓縮。如果試圖gizp壓縮這些文件的話(huà)不但會浪費(fèi)CPU資(zī)源還會增加文件的大(dà)小(xiǎo)。      

Gzip壓縮所有可能的文件類型是減少文件體(tǐ)積增加用戶體(tǐ)驗的簡單方法。


14、配置ETag      

Entity tags(ETags)(實體(tǐ)标簽)是web服務器和浏覽器用于判斷浏覽器緩存中(zhōng)的内容和服務器中(zhōng)的原始内容是否匹配的一(yī)種機制(“實體(tǐ)”就是所說的“内容”,包括圖片、腳本、樣式表等)。增加ETag爲實體(tǐ)的驗證提供了一(yī)個比使用“last-modified date(上次編輯時間)”更加靈活的機制。Etag是一(yī)個識别内容版本号的唯一(yī)字符串。唯一(yī)的格式限制就是它必須包含在雙引号内。原始服務器通過含有ETag文件頭的響應指定頁面内容的ETag。

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

稍後,如果浏覽器要驗證一(yī)個文件,它會使用If-None-Match文件頭來把ETag傳回給原始服務器。在這個例子中(zhōng),如果ETag匹配,就會返回一(yī)個304狀态碼,這就節省了12195字節的響應。      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的問題在于,它是根據可以辨别網站所在的服務器的具有唯一(yī)性的屬性來生(shēng)成的。當浏覽器從一(yī)台服務器上獲得頁面内容後到另外(wài)一(yī)台服務器上進行驗證時ETag就會不匹配,這種情況對于使用服務器組和處理請求的網站來說是非常常見的。默認情況下(xià),Apache和IIS都會把數據嵌入ETag中(zhōng),這會顯著減少多服務器間的文件驗證沖突。      

Apache 1.3和2.x中(zhōng)的ETag格式爲inode-size-timestamp。即使某個文件在不同的服務器上會處于相同的目錄下(xià),文件大(dà)小(xiǎo)、權限、時間戳等都完全相同,但是在不同服務器上他們的内碼也是不同的。      

IIS 5.0和IIS 6.0處理ETag的機制相似。IIS中(zhōng)的ETag格式爲Filetimestamp:ChangeNumber。用ChangeNumber來跟蹤IIS配置的改變。網站所用的不同IIS服務器間ChangeNumber也不相同。 不同的服務器上的Apache和IIS即使對于完全相同的内容産生(shēng)的ETag在也不相同,用戶并不會接收到一(yī)個小(xiǎo)而快的304響應;相反他們會接收一(yī)個正常的200響應并下(xià)載全部内容。如果你的網站隻放(fàng)在一(yī)台服務器上,就不會存在這個問題。但是如果你的網站是架設在多個服務器上,并且使用Apache和IIS産生(shēng)默認的ETag配置,你的用戶獲得頁面就會相對慢(màn)一(yī)點,服務器會傳輸更多的内容,占用更多的帶寬,代理也不會有效地緩存你的網站内容。即使你的内容擁有Expires文件頭,無論用戶什麽時候點擊“刷新”或者“重載”按鈕都會發送相應的GET請求。      

如果你沒有使用ETag提供的靈活的驗證模式,那麽幹脆把所有的ETag都去(qù)掉會更好。Last-Modified文件頭驗證是基于内容的時間戳的。去(qù)掉ETag文件頭會減少響應和下(xià)次請求中(zhōng)文件的大(dà)小(xiǎo)。微軟的這篇支持文稿講述了如何去(qù)掉ETag。在Apache中(zhōng),隻需要在配置文件中(zhōng)簡單添加下(xià)面一(yī)行代碼就可以了:FileETag none


15、盡早刷新輸出緩沖      

當用戶請求一(yī)個頁面時,無論如何都會花費(fèi)200到500毫秒用于後台組織HTML文件。在這期間,浏覽器會一(yī)直空閑等待數據返回。在PHP中(zhōng),你可以使用flush()方法,它允許你把已經編譯的好的部分(fēn)HTML響應文件先發送給浏覽器,這時浏覽器就會可以下(xià)載文件中(zhōng)的内容(腳本等)而後台同時處理剩餘的HTML頁面。這樣做的效果會在後台煩惱或者前台較空閑時更加明顯。      

輸出緩沖應用最好的一(yī)個地方就是緊跟在之後,因爲HTML的頭部分(fēn)容易生(shēng)成而且頭部往往包含CSS和JavaScript文件,這樣浏覽器就可以在後台編譯剩餘HTML的同時并行下(xià)載它們。

爲了證明使用這項技術的好處,Yahoo!搜索率先研究并完成了用戶測試。


16、使用GET來完成AJAX請求      

Yahoo!Mail團隊發現,當使用XMLHttpRequest時,浏覽器中(zhōng)的POST方法是一(yī)個“兩步走”的過程:首先發送文件頭,然後才發送數據。因此使用GET最爲恰當,因爲它隻需發送一(yī)個TCP包(除非你有很多cookie)。IE中(zhōng)URL的最大(dà)長度爲2K,因此如果你要發送一(yī)個超過2K的數據時就不能使用GET了。      

一(yī)個有趣的不同就是POST并不像GET那樣實際發送數據。根據HTTP規範,GET意味着“獲取”數據,因此當你僅僅獲取數據時使用GET更加有意義(從語意上講也是如此),相反,發送并在服務端保存數據時使用POST。


17、把樣式表置于頂部      

在研究Yahoo!的性能表現時,我(wǒ)(wǒ)們發現把樣式表放(fàng)到文檔的内部似乎會加快頁面的下(xià)載速度。這是因爲把樣式表放(fàng)到内會使頁面有步驟的加載顯示。      

注重性能的前端服務器往往希望頁面有秩序地加載。同時,我(wǒ)(wǒ)們也希望浏覽器把已經接收到内容盡可能顯示出來。這對于擁有較多内容的頁面和網速較慢(màn)的用戶來說特别重要。向用戶返回可視化的反饋,比如進程指針,已經有了較好的研究并形成了正式文檔。在我(wǒ)(wǒ)們的研究中(zhōng)HTML頁面就是進程指針。當浏覽器有序地加載文件頭、導航欄、頂部的logo等對于等待頁面加載的用戶來說都可以作爲可視化的反饋。這從整體(tǐ)上改善了用戶體(tǐ)驗。      

把樣式表放(fàng)在文檔底部的問題是在包括Internet Explorer在内的很多浏覽器中(zhōng)這會中(zhōng)止内容的有序呈現。浏覽器中(zhōng)止呈現是爲了避免樣式改變引起的頁面元素重繪。用戶不得不面對一(yī)個空白(bái)頁面。      

HTML規範清楚指出樣式表要放(fàng)包含在頁面的區域内:“和不同,隻能出現在文檔的區域内,盡管它可以多次使用它”。無論是引起白(bái)屏還是出現沒有樣式化的内容都不值得去(qù)嘗試。最好的方案就是按照HTML規範在文檔内加載你的樣式表。


18、避免使用CSS表達式(Expression)      

CSS表達式是動态設置CSS屬性的強大(dà)(但危險)方法。Internet Explorer從第5個版本開(kāi)始支持CSS表達式。下(xià)面的例子中(zhōng),使用CSS表達式可以實現隔一(yī)個小(xiǎo)時切換一(yī)次背景顔色:background-color: expression( (new Date()).getHours()%2 ? "#B8D4FF" : "#F08A00" ); 如上所示,expression中(zhōng)使用了JavaScript表達式。CSS屬性根據JavaScript表達式的計算結果來設置。expression方法在其它浏覽器中(zhōng)不起作用,因此在跨浏覽器的設計中(zhōng)單獨針對Internet Explorer設置時會比較有用。      

表達式的問題就在于它的計算頻(pín)率要比我(wǒ)(wǒ)們想象的多。不僅僅是在頁面顯示和縮放(fàng)時,就是在頁面滾動、乃至移動鼠标時都會要重新計算一(yī)次。給CSS表達式增加一(yī)個計數器可以跟蹤表達式的計算頻(pín)率。在頁面中(zhōng)随便移動鼠标都可以輕松達到10000次以上的計算量。      

一(yī)個減少CSS表達式計算次數的方法就是使用一(yī)次性的表達式,它在第一(yī)次運行時将結果賦給指定的樣式屬性,并用這個屬性來代替CSS表達式。如果樣式屬性必須在頁面周期内動态地改變,使用事件句柄來代替CSS表達式是一(yī)個可行辦法。如果必須使用CSS表達式,一(yī)定要記住它們要計算成千上萬次并且可能會對你頁面的性能産生(shēng)影響。


19、使用外(wài)部JavaScript和CSS      

很多性能規則都是關于如何處理外(wài)部文件的。但是,在你采取這些措施前你可能會問到一(yī)個更基本的問題:JavaScript和CSS是應該放(fàng)在外(wài)部文件中(zhōng)呢還是把它們放(fàng)在頁面本身之内呢?      

在實際應用中(zhōng)使用外(wài)部文件可以提高頁面速度,因爲JavaScript和CSS文件都能在浏覽器中(zhōng)産生(shēng)緩存。内置在HTML文檔中(zhōng)的JavaScript和CSS則會在每次請求中(zhōng)随HTML文檔重新下(xià)載。這雖然減少了HTTP請求的次數,卻增加了HTML文檔的大(dà)小(xiǎo)。從另一(yī)方面來說,如果外(wài)部文件中(zhōng)的JavaScript和CSS被浏覽器緩存,在沒有增加HTTP請求次數的同時可以減少HTML文檔的大(dà)小(xiǎo)。      

關鍵問題是,外(wài)部JavaScript和CSS文件緩存的頻(pín)率和請求HTML文檔的次數有關。雖然有一(yī)定的難度,但是仍然有一(yī)些指标可以一(yī)測量它。如果一(yī)個會話(huà)中(zhōng)用戶會浏覽你網站中(zhōng)的多個頁面,并且這些頁面中(zhōng)會重複使用相同的腳本和樣式表,緩存外(wài)部文件就會帶來更大(dà)的益處。      

許多網站沒有功能建立這些指标。對于這些網站來說,最好的堅決方法就是把JavaScript和CSS作爲外(wài)部文件引用。比較适合使用内置代碼的例外(wài)就是網站的主頁,如Yahoo!主頁和My Yahoo!。主頁在一(yī)次會話(huà)中(zhōng)擁有較少(可能隻有一(yī)次)的浏覽量,你可以發現内置JavaScript和CSS對于終端用戶來說會加快響應時 間。      

對于擁有較大(dà)浏覽量的首頁來說,有一(yī)種技術可以平衡内置代碼帶來的HTTP請求減少與通過使用外(wài)部文件進行緩存帶來的好處。其中(zhōng)一(yī)個就是在首頁中(zhōng)内置JavaScript和CSS,但是在頁面下(xià)載完成後動态下(xià)載外(wài)部文件,在子頁面中(zhōng)使用到這些文件時,它們已經緩存到浏覽器了。


20、削減JavaScript和CSS      

精簡是指從去(qù)除代碼不必要的字符減少文件大(dà)小(xiǎo)從而節省下(xià)載時間。消減代碼時,所有的注釋、不需要的空白(bái)字符(空格、換行、tab縮進)等都要去(qù)掉。在JavaScript中(zhōng),由于需要下(xià)載的文件體(tǐ)積變小(xiǎo)了從而節省了響應時間。精簡JavaScript中(zhōng)目前用到的最廣泛的兩個工(gōng)具是JSMin和YUI Compressor。YUI Compressor還可用于精簡CSS。      

混淆是另外(wài)一(yī)種可用于源代碼優化的方法。這種方法要比精簡複雜(zá)一(yī)些并且在混淆的過程更易産生(shēng)問題。在對美國前10大(dà)網站的調查中(zhōng)發現,精簡也可以縮小(xiǎo)原來代碼體(tǐ)積的21%,而混淆可以達到25%。盡管混淆法可以更好地縮減代碼,但是對于JavaScript來說精簡的風險更小(xiǎo)。      

除消減外(wài)部的腳本和樣式表文件外(wài),