網站的首頁響應速度極其重要,這直接決定了新用戶是選擇留下還是選擇放棄你的站點。有統計數據顯示,用戶的耐心通常<2秒。最好能讓你的頁面在2秒內呈現,起碼部分呈現,否則時間越往后,你的站點被用戶放棄的可能性越將指數級上升。
提高頁面響應速度的需要考慮很多方面,其中非常重要的一項就是盡量減少HTTP請求的次數。
通常網站會對腳本文件和CSS文件進行了合并處理,這樣用戶在第一次無任何緩存的前提下,(統計數據顯示)訪問米國排名前十的門戶網站平均只會加載6-7個腳本文件和1-2個CSS文件。合并處理大大減少了HTTP請求的次數。那么圖片呢?本篇將探討一下如何技巧性地加載圖片的方式以提高網站響應速度。
- 圖片內聯
- CSS Sprites
- Image Map
圖片內聯
常見的加載圖片的方式如:<img src=”img/25/1.jpg” />
會導致一次HTTP請求,請求服務器回傳圖片。其實圖片的本質也是數據,如果能直接獲得圖片的數據,就可以直接讓屏幕繪制該圖片,避免了HTTP請求。
獲取圖片數據可以用FileReader的readAsDataURL方法,你也可以參照HTML5 Doctor里關于生成圖片預覽的說明,原理都是一樣的。
用JS寫個小工具,代碼其實沒幾行,如果懶得寫。也有現成的工具站點如Encode Data URL(有興趣可以查看該頁面源碼,同樣是通過File API實現的,原理也是一樣的),可以讓你輕松獲取圖片的數據。獲取到的數據被封裝到了Data URL里,之后將Data URL傳遞給img的src或background-image的URL等屬性即可實現圖片內聯。
例如將本地圖片拖動到工具站點Encode Data URL里,自動生成的Data URL:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg……U+LQ/9k=
//data:image/jpg;為數據協議及類型名
//base64為數據編碼格式
//后面一串就是經Base64編碼后的圖片數據了
將上面的Data URL直接塞入CSS端的img的src屬性里即可:<img src=”data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg…U+LQ/9k=” />
現在瀏覽器可以直接顯示圖片,不必再通過HTTP請求和服務器交互了。而且因為是瀏覽器直接顯示,規避了跨域的問題。
但圖片內聯也不是沒有缺點的:
- 比如圖片一旦更新就需要同步更新CSS里Data URL的值,而用普通的圖片加載方式的話,服務器端直接替換同名圖片即可。
- 比如Base64編碼后數據大小會變大,因此將Data URL寫入CSS后,CSS增加的大小會大于圖片的實際大小。雖然CSS可以gzip壓縮,而圖片不能壓縮,但龐大的CSS文件是不可取的。
- 比如舊版本的IE6/7不支持(說真的,放棄它們吧)。
結合內聯圖片的優缺點,圖片內聯最好用于很少變更,且實際尺寸很小的圖片。
CSS Sprites
CSS Sprites將多張圖片合并成一張。所謂一圖勝千言:
合并成一張圖片后,原本多次HTTP請求減少為1次。加載后用background-position位置偏移來顯示需要的圖片。例如:
#navbar span {
width: 31px;
height: 31px;
float: left;
background-image:url(/images/navbar.gif);
}
.nav1 {background-position:0 0; margin-right:4px;}
.nav2 {background-position:-32px 0; margin-right:4px;}
.nav3 {background-position:-64px 0; margin-right:4px;}
……
按常理合并圖片后邊緣處會有一些多余的空白部分,理應合并后尺寸變大才對。但出乎預料的是多張圖片合并成一張后,合并后的尺寸要比多張圖片加起來的尺寸要小。因為可以共享色表,而單獨的一張圖片會有單獨的色表。
CSS Sprites的缺點主要是后期維護困難,一旦圖片要發生變動,很容易導致CSS里位置重新計算偏移量。況且Photoshop切圖合并也不是很容易的事。
因此CSS Sprites一般用于不常變動的背景,按鈕,導航條,鏈接等地方。但如果圖片太多,一張龐大的合并圖可能是后期維護的惡夢。
Image Map
如上例用CSS Sprites合并成一張導航條圖片后,還可以用Image Map。用<map>標簽直接在一張圖片上綁定多個連接,這樣就不需要background-position位置偏移來顯示圖片了:
<img usemap="#map1" src="/images/navbar.gif">
<map name="map1">
<area shape="rect" coords="0,0,31,31" href="nav1.html" title="nav1">
<area shape="rect" coords="36,0,66,31" href="nav2.html" title="nav2">
<area shape="rect" coords="71,0,101,31" href="nav3.html" title="nav3">
……
</map>
效果顯然易見,如果你想在圖片不同區域點擊獲得不同效果,可以告別請求多張圖片并在頁面端拼圖的方式了。在本地處理合并好圖片后,用Image Map可以有效減少HTTP請求數量。
總結
圖片是網頁不可或缺的一部分,而且加載圖片通常比較吃帶寬,對圖片應該盡量用緩存和CDN來加快頁面顯示速度。但首次訪問站點沒有緩存或緩存過期時,上面3種方式(僅我所知)可以減少HTTP請求次數,并部分縮小圖片尺寸,來加速頁面的響應的速度。