《高性能網(wǎng)站建設指南》讀書筆記

減少HTTP請求

圖片地圖

// 示例代碼
<img usemap="#map1" src="...">
<map name="map1">
    <area shape="rect" coords="0,0,31,31">
    ...
</map>

CSS Sprites

合并圖片,使用CSS背景定位。

內(nèi)聯(lián)圖片

通過使用data:URL模式可能在web頁面上包含圖片但無需任何額外的HTTP請求。

data:URL除了可以用于內(nèi)聯(lián)圖片,還可以用在任何需要指定URL的地方,包括script和a標簽。

缺點是不受IE支持,另外可能存在數(shù)據(jù)大小上的限制。

由于data:URL是內(nèi)聯(lián)在頁面上的,在跨越不同頁面時不會被緩存。在這種情況下,聰明的作法是使用CSS并將內(nèi)聯(lián)圖片作為背景。將該CSS規(guī)則放在外部樣式表中,這意味著數(shù)據(jù)可以緩存在樣式表內(nèi)部。

合并腳本和樣式表

在開發(fā)環(huán)境下分模塊,在生產(chǎn)環(huán)境下合并腳本和樣式表。

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

只有10% ~ 20%的最終用戶響應時間花在下載HTML文檔上。其余的80% ~ 90%時間花在了下載頁面中的所有組件上。

使用CDN將組件Web服務器分散開(組件服務器離用戶距離越近,響應時間越短),不僅能達到響應時間大幅減少的目的,而且還很容易實現(xiàn)。

添加Expires頭

Web服務器使用Expires頭來告訴Web客戶端它可以使用一個組件的當前副本,來減少HTTP請求。

Expires: Mon, 15 Apr 2024 20:00:00 GMT

Cache-Control: max-age

Expires頭使用一個特定的時間,它要求服務器跟客戶端嚴格同步。HTTP1.1引入了cache-control頭來克服Expires頭的限制。

Cache-Control使用max-age指定組件被緩存多久,一個長久的的max-age頭可以將刷新窗設置為未來10年。

Cache-Control: max-age=315360000

Expires-Default

Apache模塊的mod_expires提供Expires-Default指令同時向響應中發(fā)送Expires頭和Cache-Control max-age頭。(跨瀏覽器改善緩存的最佳解決方案)

當我們需要更改緩存中的文件時,最有效的解決方案是修改其鏈接,這樣,全新的請求將從服務器下載最新的內(nèi)容。雅虎的做法是將版本號嵌入文件名中。

當我們沒有使用Expires頭時,瀏覽器也會有緩存,只不過瀏覽器會向服務器發(fā)送一條GET請求,確定是否要使用緩存中文件。

壓縮組件

從HTTP1.1開始,Web客戶端可以通過HTTP請求中的Accept-Encoding頭來表示對壓縮的支持:

Accept-Encoding: gzip, deflate

如果Web服務器看到請求中有這個頭,就會使用客戶端列出來的方法中的一種來壓縮響應。Web服務器通過響應中的Content-Encoding來通知Web客戶端:

Content-Encoding: gzip

代理緩存

可以通過設置Vary: Accept-Encoding讓代理服務器緩存壓縮和未壓縮的響應,以滿足不同瀏覽器的需求(瀏覽器是否支持如gzip)。

邊緣情形

發(fā)送內(nèi)容到不支持它的客戶端,忘記將壓縮內(nèi)容聲明為已經(jīng)進行了gzip編碼等,頁面都會被破壞。

  • 如果你的網(wǎng)站用戶很少,并且他們處在一個小圈子中(例如,他們在一個intranet中,或者都使用Firefox 1.5)邊緣情形瀏覽器就不需要太多關注??梢詨嚎s內(nèi)容并使用Vary:Accept-Encoding。這樣可以通過減少組件的大小和利用代理緩存來改善用戶體驗。
  • 如果你更注意帶寬開銷,可以和前一種情況一樣——壓縮內(nèi)容并使用Vary: Accept-Encoding。這降低了服務器端的帶寬開銷并提升了代理處理的請求數(shù)量。
  • 如果你擁有大量的,多變的用戶群,能夠應付較高的帶寬開銷,并且享有高質(zhì)量的名聲,請壓縮內(nèi)容并使用Cache-Control: Private。這禁用了代理緩存但避免了邊緣情形缺陷。

將樣式表放在頂部

在IE中,將樣式表放在底部會導致出現(xiàn)“白屏”。

一個style塊可以包含多個@import規(guī)則,但@import規(guī)則必須放在所有其他規(guī)則之前。

<style>
    @import url("styles2.css");
</style>

@import規(guī)則也有可能會導致白屏現(xiàn)象,因為使用@import規(guī)則會導致組件下載時的無序性。即便把@import規(guī)則放在文檔的HEAD標簽中也是如此。

無樣式內(nèi)容的閃爍

把樣式表放在最后的情況:頁面加載時,文字首先顯示,然后是圖片,最后在樣式表正確地下載并解析之后,已經(jīng)呈現(xiàn)的文字和圖片要用新的樣式重繪了,這就是“無樣式內(nèi)容的閃爍”。而白屏現(xiàn)象正是對這個問題的彌補。

將腳本放在底部

下載腳本時并行下載實際上是被禁用的,即使使用了不同的主機名,瀏覽器也不會啟動其他的下載。其中一個原因是,腳本可能使用document.write來修改頁面內(nèi)容,因此瀏覽器會等待,以確保頁面能夠恰當?shù)夭季帧?/p>

在下載腳本時瀏覽器阻塞并行下載的另一個原因是為了保證腳本能夠按照正確的順序執(zhí)行。如果并行下載多個腳本,就無法保證響應是按照特定順序到達瀏覽器的。

避免CSS表達式

使用外部JavaScript和CSS

內(nèi)聯(lián)的JavaScript和CSS可以減少額外的HTTP請求,但是使用外部的JavaScript和CSS有機會被瀏覽器緩存起來,在這種情況下,HTML文檔會比使用內(nèi)聯(lián)的HTML文檔小,而且不會增加HTTP請求的數(shù)量。

使用外部JavaScript和CSS能提高組件重用率,并且易維護。

對于很多網(wǎng)站的主頁來說,使用內(nèi)聯(lián)JavaScript和CSS會是更好的選擇。然后在主頁加載完成后下載其余頁面的外部JavaScript和CSS,使其被瀏覽器緩存起來。

動態(tài)內(nèi)聯(lián)是指服務器根據(jù)cookie生成有內(nèi)聯(lián)樣式的頁面或有外部鏈接的頁面。

減少DNS查找

DNS是將域名映射到IP地址,而這個查找過程需要時間。

通常大型網(wǎng)站會使用不同的主機,以提供更多的并行下載,這樣頁面相對能夠更快地展示給用戶。但是越多的主機,意味著需要更多的DNS查找。

精簡JavaScript

避免重定向

重定向引起的延遲也很嚴重,因為它延遲了整個HTML文檔的傳輸。在HTML文檔到達之前,頁面中不會呈現(xiàn)任何東西,也沒有任何組件會被下載。

URL的結(jié)尾沒有斜線會導致一次重定向,這個是可以人為避免的。但是主機后缺少斜線時不會發(fā)生重定向,如http://www.yahoo.com,你會發(fā)現(xiàn)瀏覽器地址欄會在結(jié)尾自動添加斜線。這是因為瀏覽器在進行GET請求時必需指定路徑。如果沒有路徑,它就會簡單的使用文檔根(/)

刪除重復腳本

在一個頁面中兩次包含同一個JavaScript文件會損傷性能,因為會產(chǎn)生不必要的HTTP請求(IE)和執(zhí)行JavaScript所浪費的時間(腳本會被多次求值)。

在IE中,被緩存的文件還會發(fā)送條件GET請求,以確定緩存中的文件是否需要更新。

配置ETag

ETag(Entity Tag,實體標簽)是Web服務器和瀏覽器用于確認組件有效性的一種機制。

瀏覽器下載組件時,會將它們存儲到緩存中。在后續(xù)的頁面瀏覽中,如果緩存的組件是“新鮮的”,瀏覽器就會從磁盤上讀取它,避免產(chǎn)生HTTP請求。如果組件沒有過期,那它就是“新鮮的”,這取決于Expires頭。

如果緩存過期了,瀏覽器必須檢查它是否還有效,這時,瀏覽器會發(fā)送一個條件GET請求到服務器上進行確認。如果緩存有效,則會返回304 Not Modified的狀態(tài)碼。

檢查組件是否有效有兩種方式:

  • 比較最新修改日期
  • 比較實體標簽

瀏覽器緩存在組件和最新的修改日期,下次請求時,會使用If-Modified-Since頭將最新修改日期到服務器上比較

實體標簽就是比較緩存中的組件與原始服務器上的組件是否匹配。ETag提供了比最新修改日期更為靈活的機制,因為它可以使用組件的一些屬性來構(gòu)造。使用If-None-Match頭將ETag發(fā)送到服務器上比較。

ETag的問題是其對于服務器的唯一性,在服務器集群中,很難做到有效的驗證。所以相同的組件在不同的服務器,收到的可能就不是304響應,而是200響應,因此會下載組件的所有數(shù)據(jù)。

ETag還降低了代理緩存的效率。代理后面用戶緩存的ETag經(jīng)常和代理緩存的ETag不匹配,這導致不必要的請求被發(fā)送到原始服務器。

而且If-None-Match比If-Modified-Since優(yōu)先級高。如果請求中同時出現(xiàn)這兩個頭,則原始服務器會禁止返回304,除非請求中的條件頭字段全部一致。實際上如果根本沒有If-None-Match頭反而會更好一些。

即便組件具有長久的Expires頭,一旦用戶單擊了Reload或Refresh按鈕,仍然會產(chǎn)生條件GET請求。

使Ajax可緩存

使Ajax可緩存,除了使用Expires頭之外,最好的方式是使用查詢子符串參數(shù),如:

/ws/mail/v1/formrpc?m-GetMessage&yid=steve_souders
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容