《高性能網站建設指南》讀書筆記

減少HTTP請求

圖片地圖

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

CSS Sprites

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

內聯圖片

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

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

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

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

合并腳本和樣式表

在開發環境下分模塊,在生產環境下合并腳本和樣式表。

使用內容發布網絡(CDN)

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

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

添加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指令同時向響應中發送Expires頭和Cache-Control max-age頭。(跨瀏覽器改善緩存的最佳解決方案)

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

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

壓縮組件

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

Accept-Encoding: gzip, deflate

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

Content-Encoding: gzip

代理緩存

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

邊緣情形

發送內容到不支持它的客戶端,忘記將壓縮內容聲明為已經進行了gzip編碼等,頁面都會被破壞。

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

將樣式表放在頂部

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

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

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

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

無樣式內容的閃爍

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

將腳本放在底部

下載腳本時并行下載實際上是被禁用的,即使使用了不同的主機名,瀏覽器也不會啟動其他的下載。其中一個原因是,腳本可能使用document.write來修改頁面內容,因此瀏覽器會等待,以確保頁面能夠恰當地布局。

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

避免CSS表達式

使用外部JavaScript和CSS

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

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

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

動態內聯是指服務器根據cookie生成有內聯樣式的頁面或有外部鏈接的頁面。

減少DNS查找

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

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

精簡JavaScript

避免重定向

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

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

刪除重復腳本

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

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

配置ETag

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

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

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

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

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

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

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

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

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

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

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

使Ajax可緩存

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

/ws/mail/v1/formrpc?m-GetMessage&yid=steve_souders
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374