久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

提高 Web 站點(diǎn)性能的最佳實(shí)踐

 歆馨 2014-07-07

原文地址:http://developer.yahoo.com/performance/rules.html

 

本文在尊重原文基礎(chǔ)上,,盡量翻譯得通俗易懂一些。

 

本文內(nèi)容

  • 提高 Web 站點(diǎn)性能的最佳實(shí)踐
  1. 最大限度減少 HTTP 請求
  2. 使用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)
  3. 添加 Expires 或 Cache – Control 頭
  4. Gzip 組件
  5. CSS 放在頁面頂部
  6. JavaScript 放在頁面底部
  7. 避免 CSS 表達(dá)式
  8. 使用外部 JavaScript 和 CSS
  9. 減少 DNS 查詢
  10. 精簡 JavaScript 和 CSS
  11. 避免重定向
  12. 刪除重復(fù)的腳本
  13. 配置 ETags
  14. 使得 Ajax 可緩存
  15. 盡早強(qiáng)制地發(fā)送緩沖給客戶端
  16. 用 GET 發(fā)送 Ajax 請求
  17. 延遲加載組件
  18. 預(yù)加載組件
  19. 減少 DOM 元素數(shù)量
  20. 根據(jù)域名劃分頁面內(nèi)容
  21. 最小化 iframe 數(shù)量
  22. 不要出現(xiàn) 404 錯誤
  23. 減小 Cookie 的大小
  24. 對組件使用無 coockie 域名
  25. 最小化 DOM 訪問
  26. 開發(fā)智能的事件處理程序
  27. 用 <link> 代替 @import
  28. 避免使用濾鏡
  29. 優(yōu)化圖像
  30. 優(yōu)化 CSS Sprites
  31. 不要在 HTML 中縮放圖像
  32. favicon.ico 要小且可緩存
  33. 保持組件 25K 以下
  34. 把組件打包到一個 Multipart 文檔
  35. 避免圖片 src 屬性為空
  • 修改記錄

 

下面是使頁面更快的35個最佳實(shí)踐,,它們被劃分為7個類別,。

類別: content、server,、cookie,、css、javascript,、images,、mobile

(Yahoo 開發(fā)的瀏覽器插件 YSLOW,利用這七個類作為評價頁面的指標(biāo))

最大限度減少 HTTP 請求

類別: content

最終用戶(the end-user)80%的響應(yīng)時間花費(fèi)在前端(the front-end),。大部分時間用來下載頁面中的所有組件:圖像,、CSS、JS,、Flash 等,。因此,反過來,,減少頁面組件的數(shù)量,,就可以減少渲染(呈現(xiàn))頁面所需的 HTTP 請求的數(shù)量,。這是加快頁面的關(guān)鍵。

一個方法當(dāng)然是簡化頁面設(shè)計(jì),,減少頁面組件的數(shù)量,。但是否有方法,既構(gòu)建具有豐富內(nèi)容的網(wǎng)頁,,也實(shí)現(xiàn)了快速響應(yīng),?下面是減少 HTTP 請求數(shù)量的技巧,也提供了豐富的網(wǎng)頁設(shè)計(jì),。

  • 合并文件,。通過把所有腳本或 CSS 合并到一個單獨(dú)的文件,來減少 HTTP 請求的數(shù)量,。當(dāng)在不同的頁面中,,腳本和 CSS 都不太一樣時,合并就比較困難,。你可以把合并放到最后部署時,,從而改進(jìn)響應(yīng)時間。
  • CSS 精靈(CSS Sprites),。CSS Sprites是減少圖像請求數(shù)量的首選方法,。把你的背景圖像合并到一個單獨(dú)的圖像,并且使用CSS 的“background-image”和“background-position”屬性,,來顯示你所需的圖像部分,。

CSS Sprites 是一種 CSS 圖像拼合技術(shù),一種網(wǎng)頁圖片應(yīng)用處理方式,。

  • 圖像地圖(Image maps),。把多個圖像合并到一個單獨(dú)的圖像。合并前與合并后的圖像總體大小相同,,而且減少了HTTP請求的數(shù)量,,加快了頁面速度,。但只有當(dāng)圖像在頁面中是連續(xù)的,,Image maps才好用,如導(dǎo)航欄,。定義圖像地圖的坐標(biāo)很枯燥,,而且容易出錯。對導(dǎo)航使用圖像地圖不具有可訪問性,,所以不推薦,。
  • 內(nèi)嵌圖片(Inline images)。在頁面中,,使用 data: URL scheme 嵌入圖像數(shù)據(jù),。這會增加頁面大小,。Inline images 與 CSS(已緩存)相結(jié)合可以減少 HTTP 請求,避免增加頁面大小,。目前,,所有主流瀏覽器尚不支持 Inline images。

減少頁面的HTTP請求的數(shù)量首選要做的事,,對于改善用戶初次訪問頁面的性能,,這是最重要準(zhǔn)則。正如 Tenni Theurer 在其文章 Browser Cache Usage - Exposed! 指出的,,每天訪問你網(wǎng)站的 40-60% 人都是無緩存的(都是初次訪問,,無本地緩存)。使頁面對初次訪問更快,,是更好的用戶體驗(yàn)的關(guān)鍵,。這些首次訪問者的頁面快速更好的用戶體驗(yàn)是關(guān)鍵。

批注

一個頁面往往包含很多資源,,比如圖像,、JS、CSS 等,,而這些資源都在服務(wù)器上,,客戶端若想顯示這個頁面,必須通過網(wǎng)絡(luò)從服務(wù)器下載資源到本地,??上攵m然每個資源都很小,,也就在幾十 K 左右,,但是數(shù)量很多,客戶端每次需要這樣資源,,都會到服務(wù)器上下載,,因此,減少下載的次數(shù),,或是下載完后,,直接從瀏覽器緩存里獲得,將很有意義,。

本節(jié)的技巧:合并文件,、CSS Sprites、Image maps,、Inline images 都是為了減少下載次數(shù),。比如,如果一個頁面需要三個 CSS,,那么在用戶初次訪問頁面時,,需要向服務(wù)器請求三次,。因此,若將這三個 CSS 合并成一個,,那么只需下載一次,;圖像也是如此,一個頁面最多的就是圖像,,試想網(wǎng)站的導(dǎo)航條,,與其為每個操作都搞一個圖片,倒不如將這些圖片合并在一個圖像上,,再通過 CSS 獲得圖片局部區(qū)域,。

 

使用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)

類別: server

用戶“接近”你Web服務(wù)器的程度會影響響應(yīng)時間。把內(nèi)容部署在多個,、地理位置分散的服務(wù)器上,,會使頁面加載的速度從用戶角度看更快。但是我們應(yīng)該從哪里開始,?

作為實(shí)現(xiàn)地理位置分散內(nèi)容的第一步,,不要試圖重新設(shè)計(jì)你的Web應(yīng)用程序,使它運(yùn)行在一個分布式的結(jié)構(gòu)中,。根據(jù)應(yīng)用程序,,改變結(jié)構(gòu),包括跨服務(wù)器同步會話狀態(tài)和復(fù)制數(shù)據(jù)庫事務(wù)等,,這些艱巨的任務(wù),。根據(jù)不同的應(yīng)用,改變結(jié)構(gòu)可以包括跨服務(wù)器的位置同步會話狀態(tài)和復(fù)制數(shù)據(jù)庫交易等艱巨任務(wù),。嘗試減少用戶和內(nèi)容之間的距離,,可以延遲,或從不通過,,這是應(yīng)用程序結(jié)構(gòu)的步驟,。

記住,最終用戶的80-90% 響應(yīng)時間花費(fèi)在下載所有頁面的組件:圖像,、CSS,、JS、Flash 等,,這是提高性能的黃金法則,。最好先分散你的靜態(tài)內(nèi)容,,如圖像,、CSS、JS,、Flash 等,,而不是重新設(shè)計(jì)應(yīng)用程序結(jié)構(gòu)艱巨的工作開始,。由于內(nèi)容發(fā)布網(wǎng)絡(luò),不僅大幅度減少了響應(yīng)時間,,而且簡化了應(yīng)用程序,。

一個 CDN 是一個處于多個位置的 Web 服務(wù)器的集合,更有效地向用戶發(fā)送內(nèi)容,。選擇哪個服務(wù)器發(fā)送內(nèi)容給特定用戶通常是基于一個網(wǎng)絡(luò)評估,。例如,選擇最少的網(wǎng)絡(luò)跳數(shù)或最快的響應(yīng)時間,。

一些大型的互聯(lián)網(wǎng)公司擁有自己的 CDN,,而通過 CDN 服務(wù)提供商,如 Akamai Technologies,, EdgeCast 或  level3,,成本則很高。對于剛成立的公司和私人站點(diǎn),,一個 CDN 服務(wù)的成本可以讓人望而卻步,,但當(dāng)你越來越受關(guān)注,并全球化時,,一個 CDN 是必需的,,以便快速響應(yīng)。以 Yahoo! 為例,,他們把靜態(tài)內(nèi)容從應(yīng)用程序中移到 CDN(上面提到 CDN 服務(wù)提供商,,以及他們自己的 CDN)上,提高了最終用戶 20% 以上的響應(yīng)時間,。使用 CDN 是一個只需要相對簡單地修改代碼,,顯著改善站點(diǎn)速度的方法。

批注

客戶端訪問服務(wù)器,,要經(jīng)過路由,,是要計(jì)算代價的,最小跳數(shù)也好,,最少響應(yīng)時間也罷,,所以將自己的網(wǎng)站內(nèi)容部署在多個地理位置是有必要的。

 

添加 Expires 或 Cache – Control 頭

類別: server

此規(guī)則有兩個方面:

  • 對于靜態(tài)組件:設(shè)置 Expires 頭為 "Never expire" 策略——“永不過期”,;
  • 對于動態(tài)組件:使用適當(dāng)?shù)?Cache – Control 頭,,幫助瀏覽器有條件地發(fā)送請求。

隨著頁面越來越豐富,,這意味著更多的 JS,、CSS、圖像和 Flash。一個初次訪問頁面的用戶會發(fā)出很多 HTTP 請求,,但是通過 Expires 頭,,你可以使那些組件被瀏覽器緩存。在之后的頁面瀏覽,,就避免了不必要的 HTTP 請求,。Expires 頭經(jīng)常用在圖像,但也可以用在包括 JS,、CSS 和 Flash 所有組件,。

瀏覽器(和代理)使用緩存來減少 HTTP 請求的次數(shù)和規(guī)模,使頁面加載速度更快,。一個 Web 服務(wù)器在 HTTP 響應(yīng)中使用 Expires 頭,,會告訴客戶端這個組件被緩存多長時間。下面 Expires 頭告訴瀏覽器,,這個響應(yīng)直到 2011年4月15日 都是可靠的,。

Expires: Thu, 15 Apr 2011 20:00:00 GMT

如果你的服務(wù)器是 Apache,使用 ExpiresDefault 指令來設(shè)置相對于當(dāng)前日期的過期時間,。下面例子 ExpiresDefault 指令設(shè)置過期時間為發(fā)出請求后的 10年,。

ExpiresDefault "access plus 10 years"

記住,如果使用 Expires 頭,,那么當(dāng)組件改變時,,你必須改變組件的文件名。以 Yahoo 為例,,常常使這步作為生成過程的一部分:一個版本號內(nèi)置在組件文件名,,如 yahoo_2.0.6.js。

使用 Expires 頭只影響那些用戶已經(jīng)瀏覽過的頁面,。當(dāng)用戶初次訪問,,瀏覽器緩存為空時,不會影響 HTTP 請求的數(shù)量,。因此,,這種性能改善的影響取決于用戶多長時間會在 primed cache (primed cache 是已經(jīng)包含頁面中的所有組件,它與 Empty Cache 相對)命中你的頁面,。我們在 Yahoo 做了測試,,發(fā)現(xiàn)在 primed cache 瀏覽頁面的頻率是 75-85 %。通過使用 Expires 頭,,增加被瀏覽器緩存的組件數(shù)量,,在接下來的瀏覽中可以重用,而無需通過用戶的網(wǎng)絡(luò)連接發(fā)送任何字節(jié),。

批注

根據(jù) Yahoo 的統(tǒng)計(jì),,用戶從緩存中獲得頁面所有組件的頻率在 75-85 %,,那么我們很有必要告訴瀏覽器如何緩存頁面資源。比如圖像,、CSS 這樣的靜態(tài)資源,就告訴瀏覽器永不過期,。而對動態(tài)資源,,則告訴瀏覽器,要有條件的請求,,別重新請求,。

 

Gzip 組件

類別: server

通過網(wǎng)絡(luò)傳輸 HTTP 請求和響應(yīng)所花費(fèi)的時間,可以通過前端機(jī)制而得到顯著減少,。事實(shí)上,,最終用戶的寬帶速度、Internet 服務(wù)器提供商,、點(diǎn)對點(diǎn)交換接近程度等等,,因素不是開發(fā)團(tuán)隊(duì)能控制的,但是,,還有其他影響響應(yīng)時間的因素(這些是可以控制的),。壓縮,通過減小 HTTP 響應(yīng)的大小,,來減少響應(yīng)時間,。

從 HTTP/1.1 開始,Web 客戶端用 HTTP 請求中的 Accept – Encoding 頭來指示是否支持壓縮,。

Accept-Encoding: gzip, deflate

如果 Web 服務(wù)器在請求中看到這個頭,,它可以利用客戶端列出的方法之一壓縮響應(yīng)。Web服 務(wù)器通過響應(yīng)的 Content – Encoding 頭通知客戶端,。

Content-Encoding: gzip

Gzip 是目前最流行和最有效的壓縮方法,。它是由 GNU 開發(fā)的項(xiàng)目,并通過 RFC 1952 標(biāo)準(zhǔn)化,。你可能看過其他壓縮格式——deflate,,但它的效率較差,不太流行,。

Gzip 壓縮一般可以減少約 70% 的響應(yīng)大小,。目前大約有 90% 通過瀏覽器的互聯(lián)網(wǎng)流量,都聲稱支持Gzip,,今天的互聯(lián)網(wǎng)流量約 90% 穿過聲稱支持 gzip 的瀏覽器,。如果你使用 Apache,配置 Gzip 模塊取決于你的版本:Apache 1.3 使用 mod_gzip ,,而 Apache 2.x mod_deflate,。

總所周知,瀏覽器和代理帶來的問題是,可能會導(dǎo)致瀏覽器期望的與它收到的壓縮內(nèi)容不匹配,。幸好,,這種特殊情況隨著舊式瀏覽器使用的減少在減少。Apache 模塊會自動添加變化的響應(yīng)頭來解決這個問題,。

服務(wù)器選擇什么壓縮成 gzip,,要根據(jù)文件類型,但通常很有限,。大多數(shù)網(wǎng)站壓縮他們的 HTML 文件,,腳本和 CSS 也很值得壓縮,但是很多站點(diǎn)錯過了這個機(jī)會,。事實(shí)上,,壓縮任何文本響應(yīng),包括 XML 和 JSON,,都是值得的,。圖像和 PDF 文件不應(yīng)該被壓縮,因?yàn)樗鼈円呀?jīng)被壓縮了,。試圖壓縮他們,,不僅浪費(fèi) CPU,還會潛在增加文件的大小,。

用 Gzip 壓縮盡可能多的文件類型是一種減小頁面大小,,加速用戶體驗(yàn)的簡單方法。

批注

如果你了解 HTTP 協(xié)議,,或是用相關(guān)網(wǎng)頁測試工具,,那么一定知道服務(wù)器對客戶端都響應(yīng)了些什么。瀏覽器接收這些內(nèi)容后,,解析,,并呈現(xiàn)給用戶。無論是接收 CSS ,、腳本文件,,還是圖像,那么服務(wù)器的響應(yīng)的時候,,將它們壓縮,,再發(fā)送給客戶端,就是很符合邏輯的結(jié)果,。

 

CSS 放在頁面頂部

類別:css

在研究 Yahoo! 的性能時,,我們發(fā)現(xiàn),把 CSS 放到 HEAD 標(biāo)記使得頁面加載快了,。這是因?yàn)?,?CSS 放在 HEAD 標(biāo)記使得頁面逐漸地呈現(xiàn),。

關(guān)心性能的前端工程師期望一個頁面能逐漸加載。也就是說,,我們希望瀏覽器盡快顯示內(nèi)容,。這對于擁有較多內(nèi)容的頁面和網(wǎng)速較慢的用戶來說特別重要。給用戶返回可見的反饋的重要性,,比如進(jìn)度指示,,已經(jīng)做了很好的研究,并形成了正式文檔,。在我們看來,,HTML 頁面就是進(jìn)度指示器,。當(dāng)瀏覽器逐漸加載頁面,,頭部、導(dǎo)航條,、頂部 logo 等等,,對于等待頁面加載的用戶來說,都可以作為可見的反饋信息,。這便從整體上改善了用戶體驗(yàn),。

把CSS放在接近文檔底部的問題是,阻止在很多瀏覽器上逐漸呈現(xiàn),,包括 Internet Explorer,。這些瀏覽器阻塞呈現(xiàn)是為了避免,如果式樣改變,,那么必須重繪頁面元素,。用戶不得不面對一個空白頁面,。

HTML 規(guī)范清楚地指出 CSS 要包含在頁面的 HEAD 區(qū)域:“與 A 不同,<link />只能出現(xiàn)在文檔的 HEAD 區(qū)域,盡管它可以出現(xiàn)很多次,。”無論是白屏,,還是出現(xiàn)沒有式樣的內(nèi)容,,都是不值得的。最好的解決方法就是按照 HTML 規(guī)范,,在文檔的 HEAD 里加載 CSS,。

批注

有種情況,你一定見過:當(dāng)很多人下載電影,,占了帶寬,,網(wǎng)頁要么打不開,要么打開了,,有內(nèi)容沒式樣,。瀏覽器解析服務(wù)器發(fā)過來的頁面,,總是有個順序問題的。比如,,在沒獲得 CSS 文件前,,就準(zhǔn)備呈現(xiàn)頁面是沒有意義的。

 

腳本放在頁面底部

類別:javascript

腳本帶來的問題是它阻止了并行下載,。HTTP/1.1 規(guī)范建議,,瀏覽器并行下載,每個主機(jī)不能超過 2 個組件,。如果你的圖片放在多個主機(jī)上,,那么你可以從每個主機(jī)并行下載兩個資源。然而,,當(dāng)下載腳本時,,瀏覽器就不會下載其他資源,即便資源位于不同的主機(jī),。

在某些情況下,,把腳本放在底部不太容易。比如,,如果腳本使用 document.write 向頁面插入內(nèi)容,,它就不能被往下移。這里還會有作用域問題,。很多情況下,,都會遇到這方面問題。

一個經(jīng)常用的方法是使用延遲腳本(deferred scripts),。DEFER 屬性指示,,腳本不包含 document.write,告訴瀏覽器可以繼續(xù)呈現(xiàn),。不幸的是,,F(xiàn)irefox 并不支持 DEFER 屬性。在 Internet Explorer 中,,腳本可以被延遲,,但效果可能不像期望的那樣。如果腳本可以被延遲,,那么它就可以被移到頁面的底部,,這將使頁面加載加快。

批注

這點(diǎn)很容易理解,。如果不考慮上面提到 document.write 情況,,那么絕大多數(shù)腳本,要么是創(chuàng)建頁面標(biāo)記(控件),,要么修改頁面標(biāo)記,,無論從那個角度講,,腳本最后執(zhí)行都是最合適的。

比如,,你在 HEAD 里的腳本使用了頁面的元素,,那估計(jì)腳本會報錯,因?yàn)樵啬菚r還沒有被創(chuàng)建,。所以,,CSS、JS 等頁面資源,,別亂放,。

現(xiàn)在的 Ajax 框架,比如 jQuery 的 ready 方法,,Ext.Net 的 Ext.onReady 方法等都是處于這個目的,。

 

避免 CSS 表達(dá)式

類別:css

CSS 表達(dá)式是動態(tài)設(shè)置 CSS 屬性強(qiáng)大(而危險)的方法。從 Internet Explorer 5 開始支持 CSS 表達(dá)式,,但從 IE 8 開始被廢棄,。下面例子,,使用 CSS 表達(dá)式實(shí)現(xiàn)每隔一個小時設(shè)置一次背景顏色:

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

如上所示,,CSS 表達(dá)式使用了一個 JavaScript 表達(dá)式。CSS 屬性根據(jù) JavaScript 表達(dá)式的計(jì)算結(jié)果來設(shè)置,。表達(dá)式在其它瀏覽器中不起作用,,因此,在跨瀏覽器的設(shè)計(jì)中,,針對 Internet Explorer 設(shè)置屬性會比較有用,。

CSS 表達(dá)式的問題在于它的計(jì)算頻率比我們想象得多。不僅在頁面顯示和縮放時,,也在頁面滾動,,甚至在界面上移動鼠標(biāo),都會重新計(jì)算,。給 CSS 表達(dá)式增加一個計(jì)數(shù)器可以讓我們跟蹤表達(dá)式何時計(jì)算以及計(jì)算頻率,。隨便在頁面里移動鼠標(biāo)都可以輕松達(dá)到 10000 次以上。

減少 CSS 表達(dá)式計(jì)算次數(shù)的一個方法是使用一次性的表達(dá)式,。當(dāng)?shù)谝淮斡?jì)算表達(dá)式時,,它將結(jié)果賦值給式樣屬性,并用這個值代替 CSS 表達(dá)式,。如果樣式屬性必須在頁面周期內(nèi)動態(tài)地改變,,那么一個可行的方法是使用事件處理,而不是 CSS 表達(dá)式,。如果你必須使用 CSS 表達(dá)式,,那么一定要記住,,它們可能要運(yùn)行成千上萬次,有可能會影響以哦面性能,。

批注

雖然有用,,但存在的問題很突出、更要命,。所以,,還是不要使用的好。

 

使用外部 JavaScript 和 CSS

類別:javascript,,css

很多性能規(guī)則都是如何管理外部文件,?但在你思考這些問題前,你應(yīng)該問一個更基本的問題:JavaScript 和 CSS 是應(yīng)該放在外部文件中,,還是應(yīng)該內(nèi)嵌在頁面里,?

實(shí)際中,使用外部文件通??梢蕴岣唔撁嫠俣?,因?yàn)椋琂avaScript 和 CSS 文件可以被瀏覽器緩存,。而內(nèi)嵌在 HTML 文檔中的 JavaScript 和 CSS 會在每次請求 HTML 文檔時被重新下載,。這雖然減少了所需的 HTTP 請求次數(shù),卻增加了 HTML 文檔的大小,。而另一方面,,如果 JavaScript 和 CSS 在外部文件,并被瀏覽器緩存,,那么在沒有增加 HTTP 請求次數(shù)情況下,,減少 HTML 文檔的大小。

然而,,關(guān)鍵問題是,,被緩存的外部 JavaScript 和 CSS 組件的頻率,與請求 HTML 文檔的次數(shù)有關(guān),。盡管很難量化,,但還是有很多指標(biāo)來測量它。如果用戶在每次會話中瀏覽你網(wǎng)站的多個頁面,,而這些頁面重用了 腳本 和CSS,,那么使用可以被瀏覽器緩存的外部文件將會帶來很大好處。

很多的網(wǎng)站沒能建立起這些指標(biāo),。對這些網(wǎng)站,,一般來說,最好的解決方法是把 JavaScript 和 CSS 作為外部文件來部署。適合采用內(nèi)嵌代碼的唯一例外是網(wǎng)站的主頁,,如 My Yahoo!,。主頁在每次會話中很少被瀏覽,你會發(fā)現(xiàn),,在主頁嵌入 JavaScript 和 CSS 對最終用戶的響應(yīng)時間更快,。

對于擁有較大訪問量的首頁,有一種技術(shù)可以平衡嵌入代碼帶來的減少 HTTP 請求,,與使用外部文件帶來緩存的好處,。其中一個技術(shù)就是在首頁中嵌入 JavaScript 和 CSS,但完成加載后,,動態(tài)下載外部文件,。接下來的頁面就會使用已經(jīng)被瀏覽器緩存的外部文件。

批注

既然只有外部文件才可以被瀏覽器緩存,,那么何樂不為呢,。而且嵌入到頁面腳本代碼,也不好維護(hù),,同時,,會增大頁面大小。

 

減少 DNS 查詢

類別:content

域名解析系統(tǒng)(DNS)提供域名和 IP 的映射,,就像電話本映射人名與他們的電話號碼一樣,。當(dāng)你在瀏覽器地址欄鍵入 www. 時,DNS 解析會返回給瀏覽器對應(yīng)的 IP,。DNS 解析是有時間代價的,。一般情況下,,查找給定域名對應(yīng)的 IP,,需要 20 到 120 毫秒。在這個過程中,,瀏覽器不會下載任何東西,,直到 DNS 查詢完畢。

緩存 DNS 查詢可以改善性能,。DNS 緩存發(fā)生在要一個特定的緩存服務(wù)器,,由用戶的 ISP 或本地網(wǎng)絡(luò)維護(hù),但也會緩存在用戶自己的機(jī)器上,。DNS 信息保存在操作系統(tǒng)的 DNS 緩存中(微軟 Windows 操作系統(tǒng)的 "DNS Client Service"),。大多數(shù)瀏覽器都有自己的緩存,它獨(dú)立于操作系統(tǒng)之外,。只要瀏覽器在自己的緩存維護(hù)一個 DNS 信息,,在一次請求中就不會受到操作系統(tǒng)的影響。

默認(rèn)情況下,,Internet Explorer 的 DNS 緩存為 30 分鐘,,由注冊表的 DnsCacheTimeout 規(guī)定,。Firefox 的 DNS 緩存為 1 分鐘,由配置文件 network.dnsCacheExpiration 控制(Fasterfox 為 1 小時),。

當(dāng)客戶端的 DNS 緩存為空(瀏覽器和操作系統(tǒng)的 DNS 緩存都為空),,DNS 查詢的次數(shù)等于頁面中主機(jī)的數(shù)量。這包括頁面中的 URL,、圖像,、JS、CSS,、Flash 等使用的主機(jī),。減少唯一主機(jī)名的數(shù)量就可以減少 DNS 查詢的次數(shù)。

但減少唯一主機(jī)名的數(shù)量潛在地減少了并行下載的數(shù)量,。雖然避免 DNS 查詢次數(shù)節(jié)省了響應(yīng)時間,,但是減少并行下載卻增加了響應(yīng)時間。我的原則是,,把頁面組件分割在 2 個到 4 個主機(jī)之間,。這樣就是在減少 DNS 查詢次數(shù)與較高的并行下載之間獲得了權(quán)衡。

批注

Yahoo 還真是,,任何一個環(huán)節(jié)都不放過,。但是試想一下,DNS 查詢在 20-120 毫秒之間,,這個時間里相當(dāng)于可以從服務(wù)器上下載 1-2 個幾十k的資源,,也許是 CSS 文件,也許是腳本文件,,也許是圖片,,所以減少 DNS 查詢還是很有必要的。

 

精簡 JavaScript 和 CSS

類別:javascript,,css

“精簡”是工程實(shí)踐的結(jié)論,,從代碼中去掉不必要的字符,以減少文件大小,,從而節(jié)省加載時間,。去掉代碼的所有注釋、空白字符(包括空格,、換行,、tab)。在 JavaScript 中,,這會提高響應(yīng)時間,,因?yàn)闇p少了下載文件的大小。精簡 JavaScript 代碼最流行、最廣泛的兩個工具是 JSMinYUI Compressor,。YUI Compressor 還可用于精簡 CSS,。

“混淆”是另外一種可用于源代碼優(yōu)化的方法。該方法要比精簡復(fù)雜一些,,并且混淆很可能產(chǎn)生 BUG,。在對美國前 10 名的網(wǎng)站調(diào)查中發(fā)現(xiàn),“精簡”可以縮小源代碼 21% 的體積,,而“混淆”可以達(dá)到 25%,。盡管“混淆”可以更大程度減少代碼大小,但精簡 JavaScript 的風(fēng)險更小,。

除了精簡外部 JavaScript 和 CSS,,內(nèi)嵌的 <script> 和 <style> 代碼塊也可以(應(yīng)該)精簡。即使使用 Gzip 壓縮過的 JavaScript 和 CSS,,“精簡”文件仍然可以減少 5% 以上的大小,。隨著使用的 JavaScript 和 CSS 大小的增加,精簡代碼將會獲得更大的益處,。

批注

無論是 JavaScript,,還是 CSS,所有頁面資源都是要從服務(wù)器下載的,,它們當(dāng)然是越小越好,。所以往往,三方框架,,比如 jQuery 等,,都會提供腳本文件的正式版本(精簡過的,如果你打開看一下,,密密麻麻一坨)和它們的debug版本,。

 

避免重定向

類別:content

“重定向”是通過 HTTP 狀態(tài)碼 301 和 302 完成的。下面是一個 301 響應(yīng)的 HTTP 頭:

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

瀏覽器會自動地把用戶定向到 Location 中指定的 URL,。所有重定向需要的信息位于頭中,。響應(yīng)的內(nèi)容可以是空的。無論是 301 響應(yīng),,還是 302,它們都不會被緩存,,除非增加一個額外的頭選項(xiàng),,如 Expires 或者 Cache-Control,來指定可以被緩存,。meta 標(biāo)記和 JavaScript 是另一個實(shí)現(xiàn)重定向的方法,,但是如果你必須要跳轉(zhuǎn),那最好的方法是使用標(biāo)準(zhǔn)的 3XX HTTP 狀態(tài)碼,這主要是為了確?!昂笸恕卑粹o可以正確地使用,。

需要記住的主要事情是,重定向會降低用戶體驗(yàn),。在用戶和 HTML 文檔之間插入一個跳轉(zhuǎn),,會延遲頁面中所有元素的呈現(xiàn),因?yàn)?,?HTML 文件被加載前,,頁面的任何東西都不會被呈現(xiàn),組件也不會被下載,。

經(jīng)常發(fā)生,,最浪費(fèi)的重定向,也經(jīng)常被網(wǎng)頁開發(fā)者忽略,。那就是,,URL 缺少斜杠(/),可本應(yīng)該有,。例如,,訪問 http://astrology.yahoo.com/astrology 會導(dǎo)致 301 響應(yīng)代碼的跳轉(zhuǎn),連接應(yīng)該是 http://astrology.yahoo.com/astrology/ (注意末尾的斜杠),。在 Apache 中,,可以使用 Alias 或者 mod_rewrite,或者 DirectorySlash 檢測來避免,。

另一個經(jīng)常使用重定向的情況是,,把舊網(wǎng)站連接到新網(wǎng)站。其他情況如連接網(wǎng)站的不同部分,,或根據(jù)一定條件(瀏覽器類型,、用戶賬號類型等)來引導(dǎo)用戶。使用重定向連接兩個網(wǎng)站很簡單,,只需要很少的代碼,。盡管該方法對開發(fā)者來說,減少了復(fù)雜度,,但是缺降低了用戶體驗(yàn),。一個可替代的方法是,如果兩者在同一臺服務(wù)器上,,那么可以使用 Alias 和 mod_rewrite,。如果是因?yàn)橛蛎淖兌褂弥囟ㄏ颍敲纯梢越Y(jié)合 Alias 或 mod_rewrite,,使用 CNAME(創(chuàng)建從一個域名指向另外一個域名的 DNS 記錄),。

批注

這個是有切身體會的,,尤其是使用客戶端重定向(瀏覽器重定向)時,頁面跳轉(zhuǎn)的速度實(shí)在是有點(diǎn)慢,。

 

刪除重復(fù)腳本

類別:javascript

在一個頁面中引用同一個 JavaScript 文件兩次會影響性能,。這種情況可能并不常見。在對于美國前 10 名網(wǎng)站的調(diào)查中顯示,,其中的兩家存在重復(fù)引用腳本的情況,。有兩個主要因素增加一個頁面中重復(fù)引用腳本的幾率:團(tuán)隊(duì)規(guī)模和腳本數(shù)量。當(dāng)發(fā)生這種情況時,,重復(fù)引用腳本會創(chuàng)建不必要的 HTTP 請求,,以及延緩腳本執(zhí)行,從而損害性能,。

這種不必要的 HTTP 請求發(fā)生在 Internet Explorer,,而不會在 Firefox。在 Internet Explorer 中,,如果包含引用一個外部腳本兩次,,并且它還不可緩存,那么在頁面加載期間,,它會產(chǎn)生兩次 HTTP 請求,。即使腳本可被緩存,當(dāng)頁面重新加載時,,也會產(chǎn)生額外的 HTTP 請求,。

除了產(chǎn)生多余的 HTTP 請求,多次檢查腳本也會浪費(fèi)時間,。無論腳本是否可被緩存,,在 Internet Explorer 和 Firefox 中都會發(fā)生多余的腳本執(zhí)行。

一個避免意外地引用同一個腳本兩次的方法是,,在你的系統(tǒng)中,,開發(fā)腳本管理模塊。在 HTML 頁面中包含腳本的常見方法是使用 <script > 標(biāo)記:

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

而在 PHP 中,,通過創(chuàng)建名為 insertScript 方法:

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

為了防止多次插入同一個腳本,,該方法可以解決其他腳本問題,例如依賴檢查,,為腳本文件名添加版本號,,以便使用 Expire 頭。

 

配置 ETags

類別:server

“實(shí)體標(biāo)記(Entity tags,,ETags)”是 Web 服務(wù)器和瀏覽器用于確定,,瀏覽器緩存中的組件與服務(wù)器的一個原始內(nèi)容是否匹配的一種機(jī)制?!皩?shí)體”就是“組件”:圖像,、腳本、CSS 等,。添加 ETags 會提供一種驗(yàn)證實(shí)體的機(jī)制,,這比最后修改日期 last-modified date 更加靈活。一個 ETags 是一個唯一標(biāo)識一個特定版本組件的字符串,。字符串必須用雙引號括起來,。服務(wù)器通過 ETag 響應(yīng)頭來指定組件的 ETag。

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

之后,,如果瀏覽器要驗(yàn)證一個組件,,那么它會使用 If-None-Match 頭把 ETag 回傳誒服務(wù)器。如果 ETags 匹配,,那么會返回 304 HTTP 狀態(tài)碼,,減少了 12195 字節(jié)的響應(yīng)。

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

ETags 的問題在于,,它們通常使用網(wǎng)站服務(wù)器的唯一的屬性來構(gòu)造,。當(dāng)瀏覽器從一臺服務(wù)器上獲得原始組件,之后,,嘗試驗(yàn)證另一臺服務(wù)器上的組件時,,ETags 就不會匹配。這種情況在使用集群服務(wù)器來處理請求的 Web 站點(diǎn)上相當(dāng)普遍,。默認(rèn)情況下,,Apache 和 IIS 都把數(shù)據(jù)嵌入入到 ETag 中,這樣能顯著減少在多服務(wù)器情況下,,成功在一臺服務(wù)器驗(yàn)證的幾率,。

Apache 1.3 和 2.x 的 ETag 格式是 inode-size-timestamp。即使一個給定的文件在多個服務(wù)器的相同目錄,,且具有相同的大小,、權(quán)限、時間戳等,,但它的 inode 仍然是不同的,。.

IIS 5.0 和 IIS 6.0 的 ETags 具有類似的問題。IIS 的 ETag 格式是 Filetimestamp:ChangeNumber,。ChangeNumber 是一個計(jì)數(shù)器,,用來跟蹤 IIS 配置的改變。不同的是,,ChangeNumber 在一個 Web 站點(diǎn)的所有 IIS 都是相同的,。

對于完全相同的組件,在不同的服務(wù)器上,,由 Apache 和 IIS 產(chǎn)生的 ETags 不同,。如果 ETags 不匹配,,那么用戶不會收到一個小而快的 304 響應(yīng);而是,,會得到一個正常的 200 響應(yīng),,并下載全部內(nèi)容。如果你的網(wǎng)站只在一臺服務(wù)器上,,那不會有問題,。但是如果你的網(wǎng)站架設(shè)在多個服務(wù)器,并且使用 Apache,,或默認(rèn) ETag 配置的  IIS,,那么用戶獲得頁面會相對較慢,你的服務(wù)器負(fù)載較高,,帶寬消耗較大,,代理不會有效地緩存你的內(nèi)容。即使你的組件具有 Expires 頭,,無論用戶何時點(diǎn)擊“重載”或者“刷新”,,都會發(fā)送一個有條件的 GET 請求。

如果你沒有利用 ETag 提供的靈活驗(yàn)證模式,,那么最好把 ETag 刪掉,。Last-Modified 頭是基于組件時間戳來驗(yàn)證。刪掉 ETag 會在響應(yīng)和接下來的請求中減少 HTTP 頭的大小,。Microsoft Support article 文檔描述如何刪掉 ETag,。在 Apache 中,只需要在配置文件中簡單添加下面一行代碼就可以:

FileETag none
批注

這種為資源的生成唯一標(biāo)識的做法很常見,。如果文件有改動,,那么唯一標(biāo)識一定不同。

 

使 Ajax 可緩存

類別:content

Ajax 被提到的一個好處是,,由于它從服務(wù)器異步請求信息,,能為用戶提供即時反饋。然而,,使用 Ajax 并不能保證用戶不用等待那些返回的異步 JavaScript 和 XML 響應(yīng),。在很多應(yīng)用中,用戶是否等待取決于如何使用 Ajax,。例如,,在一個基于 Web 的 Email 客戶端中,用戶必須等待 Ajax 請求的結(jié)果,,返回符合查找條件的郵件信息,。很重要的一點(diǎn),“異步”并不意味著“即時”,。

為了提高性能,,優(yōu)化 Ajax 響應(yīng)很重要,。提高 Ajxa 性能的最重要的方法是使響應(yīng)可緩存,如“添加 Expires 和 Cache-Control 頭”小節(jié)描述的,。其他幾條規(guī)則也適用于 Ajax:

  • Gzip 組件
  • 減少 DNS 查詢
  • 減小 JavaScript
  • 避免重定向
  • 配置 ETags

讓我們看一個例子:一個 Web2.0 Email 客戶端會使用 Ajax 自動下載該用戶的地址簿,。如果用戶在上次使用 Email Web 應(yīng)用程序后,,沒有修改地址簿,,那么,如果用 Expire 或者 Cacke-Control 頭設(shè)置 Ajax 可緩存,,就可以直接從緩存中讀取地址薄,。必須告訴瀏覽器,是使用緩存中的地址薄,,還是發(fā)送一個新的請求,。這可以通過給地址薄的 Ajax URL 添加一個時間戳,指示用戶最后修改地址簿的時間,,例如,,&t=11900241612。如果地址薄在上次讀取后沒有被修改過,,那么時間戳不變,,從瀏覽器的緩存中讀取地址簿,以減少額外的 HTTP 請求,。如果用戶修改了地址薄,,那么時間戳?xí)_保新的 URL 與緩存中的響應(yīng)不匹配,瀏覽器將請求新的地址簿,。

即便你的 Ajxa 響應(yīng)是動態(tài)生成的,,哪怕它只應(yīng)用于一個用戶,那也應(yīng)該把它們緩存起來,。這樣可以使你的 Web2.0 應(yīng)用程序響應(yīng)速度更快,。

 

盡早強(qiáng)制地發(fā)送緩沖給客戶端

類別:server

當(dāng)用戶請求一個頁面時,無論如何后端都會花 200 到 500 毫秒,,以便組織 HTML 頁面,。期間,瀏覽器會一直是空閑的,,直到數(shù)據(jù)到達(dá),。在 PHP 中,你可以使用 flush() 方法,,它允許你把部分 HTML 響應(yīng)發(fā)送給瀏覽器,,這樣,瀏覽器就可以開始獲取組件,,同時后臺處理 HTML 頁面的剩余部分,。這樣做好處在后端繁忙,,而前端空閑時最明顯。

考慮強(qiáng)制發(fā)送的一個最好的地方是 HEAD 后,,因?yàn)?HTML 頭通常最容易生成,,讓你可以包含任何 CSS 和 JavaScript 文件,以便瀏覽器在開始并行下載的同時,,后端仍然在處理,。 例子:

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

Yahoo! search 率先進(jìn)行了研究,真實(shí)的用戶測試表明了該技術(shù)的好處,。

批注

不用等到全部內(nèi)容都有了,,再發(fā)給客戶端,這期間用戶都看不到,。有的話,,就立刻發(fā)出去,讓頁面“慢慢”呈現(xiàn)出來,。

 

使用 GET 發(fā)送 Ajax 請求

類別:server

Yahoo!Mail 團(tuán)隊(duì)發(fā)現(xiàn),,當(dāng)使用 XMLHttpRequest 時,瀏覽器中 POST 的實(shí)現(xiàn)是兩步過程:首先發(fā)送頭,,然后才發(fā)送數(shù)據(jù),。這樣,使用 GET 最好,,因?yàn)?,它只發(fā)送一個 TCP 包(除非你有很多 cookie)。IE URL 的最大長度為 2K,,因此,,如果你要發(fā)送一個超過 2K 的數(shù)據(jù),那就不能使用 GET,。

一個有趣的副作用是,,沒有真正發(fā)送任何數(shù)據(jù)的 POST 的行為有點(diǎn)像 GET。根據(jù) HTTP 規(guī)范,,GET 意味著“檢索”數(shù)據(jù),,因此,當(dāng)你只是查詢數(shù)據(jù)時,,GET 更加有意義(從語意上也是如此),,相反,發(fā)送并在服務(wù)端保存數(shù)據(jù)時使用 POST,。

 

延遲加載組件

類別:content

你可以仔細(xì)看一下你的網(wǎng)頁,,問問自己“哪些內(nèi)容是頁面初次呈現(xiàn)所必需的?”。剩下的內(nèi)容和組件可以稍后加載,。

JavaScript 是一個理想的選擇,,按照 onload 事件分成兩部分,之前和之后,。例如,,如果你有用于完成拖拽效果的 JavaScript 和庫,那么它們可以稍后加載,,因?yàn)轫撁娴耐献г厥窃陧撁娉跏汲尸F(xiàn)后才發(fā)生的,。其他稍后加載的選擇包括隱藏的內(nèi)容(這些內(nèi)容是用戶操作后才出現(xiàn)的),以及處于折疊的圖像,。

幫你減輕該工作的工具:YUI Image Loader 可以讓你推遲加載折疊部分的圖片,。YUI Get utility 是包含 JS 和 CSS 的便捷方法。例如,,你可以用 Firebug 的 Net 選項(xiàng)卡看一下 Yahoo! Home Page

當(dāng)性能目標(biāo)體現(xiàn)在 Web 開發(fā)的最佳實(shí)踐時,,就會有很好的效果,。這種情況下,通過漸進(jìn)增強(qiáng)(progressive enhancement )的思想告訴我們,,在支持 JavaScript 的情況下,,JavaScript 可以改進(jìn)用戶體驗(yàn),但是必須確保頁面沒有JavaScript 也可以正常工作,。因此,,在確保頁面運(yùn)行正常后,用延遲加載腳本來增強(qiáng)頁面,,比如拖拽和動畫腳本,。

批注

剛開始只加載最基本,暫時不需要的組件,,就不用加載,。遵循“漸進(jìn)增強(qiáng)”原則。

 

預(yù)加載組件

類別:content

“預(yù)加載”和“延遲加載”看似相反,,但實(shí)際上“預(yù)加載”是為了實(shí)現(xiàn)另外一種目標(biāo),。通過預(yù)加載,你可以利用瀏覽器空閑的時間,,請求將來需要的組件(如圖像,、CSS 和腳本)。使用這種方法,,當(dāng)用戶要訪問下一個頁面時,,頁面的大部分組件都已經(jīng)在緩存中了,這會打打改善用戶加載頁面的速度。

下面是幾種“預(yù)加載”的方法:

  • 無條件的預(yù)加載:只要觸發(fā) onload 事件,,你就直接獲取額外的組件,。以 Google.com 為例,看一下合成的圖像是如何在 onload 中加載的,。合成中的圖像在 google.com 主頁并不需要,,但在一個“連續(xù)”的檢索結(jié)果頁面中是需要的。
  • 有條件的預(yù)加載:根據(jù)用戶的操作,,你可以推測出用戶接下來會做什么,,進(jìn)行相應(yīng)的預(yù)加載。在 search.yahoo.com 中,,你可以看到在你在文本框輸入后,,如何請求額外的組件。
  • 期望的預(yù)加載:在重新設(shè)計(jì)前,,應(yīng)先考慮預(yù)加載,。當(dāng)重新設(shè)計(jì)后,你經(jīng)常能聽到:“新的站點(diǎn)和不錯,,但比之前慢了”,。部分問題在于,用戶在完全緩存里訪問你的之前的站點(diǎn),,而新的站點(diǎn)一直是空的緩存,。因此,即便要重新設(shè)計(jì),,你也要通過預(yù)加載減輕這種副作用,。舊站點(diǎn)使用瀏覽器的空閑時間,請求新站點(diǎn)使用的圖像和腳本,。
批注

最明顯的情況是,,“翻轉(zhuǎn)”效果。

 

減少 DOM 元素數(shù)量

類別:content

一個復(fù)雜的頁面意味下載更多的數(shù)據(jù),,也就意味著 JavaScript 訪問 DOM 會變慢,。例如,當(dāng)你添加一個事件處理時,,遍歷頁面的 500 或 5000 個元素是不一樣的,。

大量的 DOM 元素是一個征兆,它意味著,,可以使用頁面標(biāo)記,,而無需刪除內(nèi)容。你是否布局而采用內(nèi)置表格,?是否僅僅為了自適應(yīng)而使用很多 DIV,?也許有一個更好,更符合語義的方法。

YUI CSS utilities 來布局很方便:grids.css 可以幫你整體布局,,font.css 和 reset.css 可以幫助你移除瀏覽器默認(rèn)的格式,。這提供了一個重新審視和思考標(biāo)記的機(jī)會,例如,,只有當(dāng)在語義上說得通時才使用<div>,,而不是因?yàn)樗艹尸F(xiàn)一個新行才使用。

DOM 元素數(shù)量很容易計(jì)算,,只需要在 Firebug 控制臺內(nèi)輸入:

document.getElementsByTagName('*').length

那么多少個 DOM 元素算多,?可以對比一下好的頁面。比如 Yahoo! Home Page 是一個內(nèi)容很多的頁面,,但它只有 700 個元素(HTML 標(biāo)簽),。

批注

頁面好看與頁面復(fù)雜總是很矛盾。夠炫的頁面往往都很復(fù)雜,,元素很多,,元素很多的話,JavaScript 訪問起來就會變慢,。

 

根據(jù)域名分割組件

類別:content

分割組件可以使你最大限度地并行下載,。由于 DNS 查找的影響,確保你使用的域名在2到4個之間,。例如,你可以把 HTML 和動態(tài)內(nèi)容放在 www.example.org 上,,而把分割的靜態(tài)組件(圖片,、腳本、CSS)放在 statics1.example.org 和 statics.example.org,。

你可以在 Tenni Theurer 和 Patty Chi 合寫的文章 "Maximizing Parallel Downloads in the Carpool Lane" 找到更多相關(guān)信息,。

批注

既然在 HTML 規(guī)范中規(guī)定資源是可以并行下載的,那么我們當(dāng)然可以將網(wǎng)站的資源分別存在不同的地方,。

 

最小化 iframe 數(shù)量

類別:content

ifrmae 元素可以在父文檔中插入一個新的 HTML 文檔,。了解 iframe 如何工作,才能有效地使用它,。

<iframe> 優(yōu)點(diǎn):

  • 幫助加載緩慢的三方部件和廣告等
  • Security sandbox
  • 并行下載腳本

<iframe> 缺點(diǎn):

  • 即便加載是空的,,也有代價
  • 會阻止頁面加載
  • 沒有語意

 

不要出現(xiàn) 404 錯誤

類別:content

HTTP 請求很昂貴。因此,,發(fā)送一個 HTTP 請求,,卻獲得一個無用的響應(yīng)(如,404 Not Found)是完全沒必要的,,它只會降低用戶體驗(yàn),,而不會有一點(diǎn)好處。

有些站點(diǎn)把 404 錯誤響應(yīng)頁面改為“你是不是要找***?”,,這雖然改進(jìn)了用戶體驗(yàn),,但卻浪費(fèi)了服務(wù)器資源(像數(shù)據(jù)庫等)。最糟糕的情況是指向一個外部 JavaScript 鏈接,,返回 404 錯誤,。首先,這個下載會阻塞并行下載,。其次,,瀏覽器會試圖解析 404 響應(yīng)的內(nèi)容,就像它是 JavaScript 代碼,,嘗試在里邊查找有用的東西,。

 

減小 Cookie 大小

類別:cookie

使用 HTTP coockie 有很多原因,比如認(rèn)證(authentication )和個性化,。在 Web 服務(wù)器與瀏覽器之間,,通過 HTTP 頭來交換 coockie 信息。盡可能維持 coockie 的大小,,以減少對用戶響應(yīng)時間的影響,,很重要。

有關(guān)更多信息,,可以查看 Tenni Theurer 和 Patty Chi 的文章 "When the Cookie Crumbles",。該文內(nèi)容的研究包括:

  • 去掉不必要的 coockie
  • 盡可能維持 coockie 的大小,以減少對用戶響應(yīng)時間的影響
  • 注意在適當(dāng)域名級別上設(shè)置 coockie,,以便其他子域不會受到影響
  • 適當(dāng)設(shè)置的過期時間,。刪除 cookie 較早的過期時間或沒有,能改善用戶的響應(yīng)時間,。

 

對組件使用無 coockie 域名

類別:cookie

當(dāng)瀏覽器請求一個靜態(tài)圖像,,并且隨請求發(fā)送 coockie 時,服務(wù)器并不會使用這些 coockie,。因此,,毫無疑問,它們(coockie )只會產(chǎn)生網(wǎng)絡(luò)流量,。你應(yīng)該確保請求靜態(tài)組件時,,請求中不帶 cookie。創(chuàng)建一個域,,把你所有的靜態(tài)組件放在該子域,。

如果你的域名是 ww.example.org,那么你可以把靜態(tài)組件放在 static.example.org 上,。然而,,如果你已經(jīng)在頂級域 example.org 設(shè)置了 coockie,,而不是在 www.example.org 上,那么,,所有對 static.example.org 的請求都將包含 coockie,。在這種情況下,你可以購買一個新域名,,存放你的靜態(tài)組件,,并讓這個域名無 coockie。Yahoo! 使用的是 ymig.com,,YouTube 使用的是 ytimg.com,,Amazon 使用 images-anazon.com 等。

使用無 coockie 域名存放靜態(tài)組件的另外一個好處是,,一些代理(服務(wù)器)可能會拒絕緩存帶 coockie 請求的組件,。相關(guān)建議是,如果你想確定是用 example.org 作為你的主頁,,還是 www.example.org,,那么,你可以考慮 coockie 帶來的影響,。沒有 www 的會把 coockie 設(shè)置到 *.example.org 的所有域,,這樣你就別無選擇了。因此,,出于性能的考慮,,最好使用 www 子域名,并在它上設(shè)置 coockie,。

 

最小化 DOM 訪問

類別:javascript

用 JavaScript 訪問 DOM 元素比較慢,,因此為了更好響應(yīng)頁面,你應(yīng)該:

  • 緩存已經(jīng)訪問過的原始
  • 離線更新完節(jié)點(diǎn)后,,再將它們添加到文檔樹中
  • 避免使用 JavaScript 來自適應(yīng)布局

有關(guān)更多信息,請查看 Julien Lecomte 的文章 "High Performance Ajax Applications",。

 

開發(fā)智能事件處理程序

類別:javascript

有時,,頁面反應(yīng)遲鈍,這是因?yàn)?,太多綁定?DOM 樹元素的事件處理,,并且被頻繁執(zhí)行。這就是為什么使用事件托管(event delegation),。如果你在一個 div 中有 10 個按鈕,,那么你只需在 div 上綁定一個事件處理(利用委托),而不是為每個按鈕,。事件冒泡時,,你可以捕捉到該事件,,并判斷出是哪個事件發(fā)出的。

你也不用為了操作 DOM 樹而等待 onload 事件,。通常,,你所需要就是訪問DOM 樹中可用的元素。你也不必等待所有圖像都加載完畢,。不用 onload,,DOMContentLoaded 是可以考慮的事件,但在所有瀏覽器都支持它之前,,你可使用 YUI Event 工具,,它有一個 onAvailable 方法。

有關(guān)更多信息,,參看 Julien Lecomte 的文章 "High Performance Ajax Applications",。

批注

換句話說,通過事件委托,,我們可以為 10 個按鈕只使用一個事件,,而不是 10 個按鈕搞 10 個事件處理。比如,,增刪改三個按鈕,,可以用一個事件來弄,事件觸發(fā)時,,可以知道當(dāng)前操作的是什么,。

 

用 <link> 代替 @import

類別:css

前面的最佳實(shí)踐提到,CSS 應(yīng)該放在頁面頂部,,以便漸進(jìn)呈現(xiàn),。

在 IE 中,@import 的行為相當(dāng)于把 <link> 放在頁面頂部,,因此最好不要使用它,。

 

避免使用濾鏡

類別:css

IE 獨(dú)有的 AlphaImageLoader 濾鏡旨在修復(fù) 7.0 以下版本的半透明真彩色 PNG 圖像問題。該濾鏡的問題是,,當(dāng)圖像正被下載時,,它會阻塞呈現(xiàn),并凍結(jié)瀏覽器,。濾鏡也會增加內(nèi)存消耗,,并被應(yīng)用到每個元素,而不是每個圖像,,因此,,濾鏡的問題是多方面的。

最好的方法是避免完全使用 AlphaImageLoader,,而是使用 PNG8,,它能在 IE 中很好地工作,。如果你確實(shí)需要使用 AlphaImageLoader,那應(yīng)該使用 hack_filter,,不會影響到 IE7 以上版本的用戶,。

 

優(yōu)化圖像

類別:images

設(shè)計(jì)人員為頁面創(chuàng)建圖像后,向 Web 服務(wù)器上傳圖像前,,你可以試著做以下幾件事:

  • 檢查 GIF 圖像,,看下圖像中的顏色數(shù)量是否與調(diào)色板一致。使用 imagemagick 可以很容易檢查:
identify -verbose image.gif 

如果你發(fā)現(xiàn)圖像中只用了 4 種顏色,,而調(diào)色板中是 256 色,,那么這張圖片就改進(jìn)的空間。

  • 嘗試把 GIF 格式轉(zhuǎn)換成 PNG 格式,,看看是否節(jié)省了空間,。多數(shù)情況下會。早先由于瀏覽器支持有限,,開發(fā)者不太愿意使用 PNG 格式,,但現(xiàn)在已經(jīng)成為過去。唯一一個問題是真彩 PNG 格式的 alpha 通道半透明問題,,不過 GIF 也不是真彩的,,并且不支持任何半透明。因此,,GIF 能做到的,,調(diào)色板 PNG(PNG8)同樣也能做到(除了動畫)。下面一條簡單的 imagemagick 命令可以把 GIF 安全地完全轉(zhuǎn)換成 PNG:
convert image.gif image.png 
  • 在你所有的 PNG 圖像上,,運(yùn)行 pngcrush(或者其它 PNG 優(yōu)化工具),。例如:
pngcrush image.png -rem alla -reduce -brute result.png 
  • 在你所有的 JPEG 圖像上運(yùn)行 jpegtran。這個工具可以對 JPEG 中出現(xiàn)的鋸齒等做無損操作,,同時,,它還可以用于優(yōu)化和清除圖像中的注釋,以及其它無用信息(如 EXIF 信息):
jpegtran -copy none -optimize -perfect src.jpg dest.jpg 

 

優(yōu)化 CSS Sprites

類別:images

  • 通常,,在 Sprite 中水平排列圖像比垂直排列的文件要小,。
  • 在一個 Sprite 中合并結(jié)合相似的顏色會幫助你保持較低的色彩數(shù),理想狀態(tài)是 256 色,,以適應(yīng)一個 PNG8。
  • "Be mobile-friendly",,并且不要在一個 Sprite 中的圖像之間留下較大的空隙,。這不會影響文件的大小,但對于迫切需要解壓縮圖像到一個像素地圖上的用戶來說,,需要更少的的內(nèi)存,。100x100 的圖像是1 萬個像素,,而 1000X1000 是 100 個萬像素。

 

不要在 HTML 中縮放圖像

類別:images

不要使用比你實(shí)際需要的大的圖像,。因?yàn)槟憧梢栽O(shè)置長寬,。如果你需要:

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

那么你的圖像(mycat.jpg)就應(yīng)該是 100x100 像素,而不是把一個 500x500 像素的圖片縮小來用,。

批注

使用多大的圖像,,就做多大的圖像。你可能見過,,往往一個內(nèi)容,,會有不同像素大小的版本,比如工具欄按鈕圖標(biāo),,同時做 16×16 像素,,和 32×32 像素的。

 

favicon.ico 要小且可緩存

類別:images

favicon.ico 是一個放在你服務(wù)器根位置的圖像,。這是個必需的邪惡,,因?yàn)椋词鼓悴魂P(guān)心它,,瀏覽器仍然會請求它,,因此,最好不要用 404 響應(yīng),。此外,,由于位于同一個服務(wù)器,每次發(fā)送 Cookie 都會請求它,。這個圖像也會干擾下載隊(duì)列,,例如,在 IE 中,,當(dāng)你在 onload 請求一個額外的組件時,,favicon 將在這些額外組件前被下載。

因此,,為了減輕 favicon.ico 弊端,,應(yīng)確保:

  • favicon 要小,最好在 1K 以下,。
  • 設(shè)置你感覺合適的 Expires 頭(若你想改變它,,但你不能重新命名它)。你可以把 Expires 頭設(shè)置為未來幾個月,。你可以檢查當(dāng)前 favicon.ico 的最后修改日期,,以便做決定。

ImageMagick 可以幫助你創(chuàng)建小的 favicons(網(wǎng)站圖例),。

批注

千萬別忘了 favicon.ico,。這是瀏覽器默認(rèn)下載的資源,。

 

保持組件 25K 以下

類別:mobile

這個限制與一個事實(shí)有關(guān),iPhone 不能緩存操作 25K 大小的組件,。注意,,這是未壓縮的大小。這個小是很重要的,,因?yàn)閱为?dú) gzip 完全不夠,。

有關(guān)更多信息,參考 Wayne Shea 和 Tenni Theurer 的文章 "Performance Research, Part 5: iPhone Cacheability - Making it Stick",。

 

把組件打包到一個 Multipart 文檔

類別:mobile

把組件打包到一個 multipart 文檔很像一個帶附件的email,,它能使你在一個 HTTP 請求中獲取多個組件(切記:HTTP 請求很昂貴)。當(dāng)你使用這個技術(shù)時,,首先要確定用戶代理是否支持(iPhone 不支持),。

 

避免圖片 src 屬性為空

類別:server

img src 屬性為空的經(jīng)常發(fā)生。它有兩種形式:

  • 直接 HTML 標(biāo)記創(chuàng)建
<img src="">
  • JavaScript 代碼創(chuàng)建
var img = new Image();
img.src = "";

這兩種形式效果相同:瀏覽器會向服務(wù)器發(fā)出另一個請求,。

  • Internet Explorer 向頁面所在的目錄,,發(fā)出一個請求。
  • Safari 和 Chrome 向?qū)嶋H頁面自身,,發(fā)出一個請求,。
  • Firefox 3 和更早版本的行為與 Safari 和 Chrome 相同,但其 3.5 版本解決了這個問題[bug 444931],,不再發(fā)送請求,。
  • Opera 當(dāng)遇到img src 屬性為空時,什么都不做,。

為什么這個行為很糟,?

  1. 發(fā)送大量不期望的流量,會使服務(wù)器癱瘓,,尤其是每天有百萬瀏覽的頁面,。
  2. 浪費(fèi)服務(wù)器的處理周期,卻產(chǎn)生一個永遠(yuǎn)不會被查看的頁面,。
  3. 可能會破壞用戶數(shù)據(jù),。如果你通過 cookie或其他方式追蹤請求中的狀態(tài),那么會有損壞數(shù)據(jù)的可能性,。即使圖像請求沒有返回圖像,,瀏覽器也會讀取和接收所有的頭,包括所有 cookies,。當(dāng)余下的響應(yīng)被丟棄,,損害可能已經(jīng)產(chǎn)生。

這種行為的根本原因是在瀏覽器中完成 URI 解析的方式。這種行為定義在 RFC 3986 - Uniform Resource Identifiers,。當(dāng)遇到一個空字符串時就作為 URI,它被看作是一個相對的 URI,,并根據(jù) 5.2 節(jié)定義的算法解決,。在 5.4 節(jié) 列出了空字符串的例子。Firefox,、Safari 和 Chrome 都按規(guī)范正確解析字符串,,而 Internet Explorer 沒有,還遵循早期的規(guī)范 RFC 2396 - Uniform Resource Identifiers(已由 RFC 3986 代替),。因此,,技術(shù)上,瀏覽器做了它們被期望做的事,,來解析相對 URI,。空字符串顯然是個意外,。

HTML5 在 4.8.2 節(jié)添加一個關(guān)于標(biāo)記的 src 屬性的描述,,指示瀏覽器不要發(fā)出額外的請求:

src 屬性必須存在,并且必須包含一個有效的 URL,,它引用一個非交互式的,、可選的、可有動畫的圖像源,,不能是頁面或腳本,。如果元素的基 URI 與文檔地址相同,那么 src 屬性必須不能為空,。

慶幸的是,,之后的瀏覽器不會存在這個問題。而不幸的是,,沒有對 <script src=""> 和 <link href=""> 的規(guī)定,。可能還是有時間調(diào)整以確保瀏覽器執(zhí)行此行為,。

該規(guī)則得到 Yahoo!'s JavaScript guru Nicolas C. Zakas 的支持,。有關(guān)更多信息,參考 "Empty image src can destroy your site",。

 

修改記錄
  • 第一次 2011-12-29

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多