HTTP是一種客戶端/服務(wù)器協(xié)議,由請(qǐng)求和響應(yīng)構(gòu)成。瀏覽器向一個(gè)特定的URL發(fā)送HTTP請(qǐng)求,URL對(duì)應(yīng)的宿主服務(wù)器發(fā)回HTTP響應(yīng)。該協(xié)議使用簡單的純文本格式。請(qǐng)求的類型有GET、POST、HEAD、PUT、DELETE、OPTIONS和TRACE。
前端性能優(yōu)化十四個(gè)規(guī)則:
1. 減少HTTP請(qǐng)求。
a. 至少80%的最終用戶響應(yīng)時(shí)間花在了頁面中的組件(圖片、腳本、樣式表、Flash等)上。
b. 改善響應(yīng)時(shí)間的最簡單途徑就是減少組件的數(shù)量,并由此減少HTTP請(qǐng)求的數(shù)量。這些技術(shù)包括圖片地圖、CSS Sprites、內(nèi)聯(lián)圖片和腳本、樣式表的合并。運(yùn)用這些技術(shù)在示例頁面上估計(jì)響應(yīng)時(shí)間減少到50%左右。
c. 圖片地圖:
優(yōu)點(diǎn):允許在一個(gè)圖片上關(guān)聯(lián)多個(gè)URL,目標(biāo)URL的選擇取決于用戶點(diǎn)擊了圖片上的那個(gè)位置。這樣既能減少HTTP請(qǐng)求,又無需改變頁面外觀感受。
缺點(diǎn):在定義圖片地圖上的區(qū)域坐標(biāo)時(shí),如果采取手工的方式則很難完成且容易出錯(cuò),而且除了矩形之外幾乎無法定義其他形狀。通過DHTML穿件的圖片地圖則在IE中無法工作。
類型:圖片地圖有兩種類型。服務(wù)器端圖片地圖將所有點(diǎn)擊提交到同一個(gè)目標(biāo)URL,向其傳遞用戶單擊的x、y坐標(biāo)。Web應(yīng)用程序?qū)⒃搙、y坐標(biāo)映射為適當(dāng)?shù)牟僮???蛻舳藞D片地圖將用戶的點(diǎn)擊映射到一個(gè)操作,而無需向后端應(yīng)用程序發(fā)送請(qǐng)求。映射通過HTML的MAP標(biāo)簽實(shí)現(xiàn)。
d. CSS Sprites
e. 內(nèi)連圖片
f. 合并腳本和樣式表
2. 使用內(nèi)容發(fā)布網(wǎng)絡(luò)(CDN)
a. 內(nèi)容發(fā)布網(wǎng)絡(luò)(CDN)是一組分布在多個(gè)不同地理位置的Web服務(wù)器,用于更加有效地向用戶發(fā)布內(nèi)容。
優(yōu)點(diǎn):縮短響應(yīng)時(shí)間、備份、擴(kuò)展存儲(chǔ)能力和進(jìn)行緩存、緩和Web流量峰值壓力。CDN用于發(fā)布靜態(tài)內(nèi)容,如圖片、腳本、樣式表和Flash,提供動(dòng)態(tài)HTML頁面會(huì)引入特殊的存儲(chǔ)需求——數(shù)據(jù)庫連接、狀態(tài)管理、驗(yàn)證、硬件和OS優(yōu)化等,這些操作比較復(fù)雜。另一方面,靜態(tài)文件更容易存儲(chǔ)并具有較少的依賴性。
缺點(diǎn):響應(yīng)時(shí)間可能會(huì)受到其他網(wǎng)站的影響,以及無法直接控制組件服務(wù)器所帶來的特殊麻煩,且嚴(yán)重依賴CDN的服務(wù)性能。
無論如何也不要使用HTTP重定向來將用戶指向到本地服務(wù)器,這會(huì)使Web頁面反應(yīng)速度變慢。
3. 添加Expires頭
a. Expires頭
瀏覽器(和代理)使用緩存來減少HTTP請(qǐng)求的數(shù)量,并減少HTTP響應(yīng)的大小,使Web頁面加載得更快。Web服務(wù)器使用Expires頭來告訴Web客戶端它可以使用一個(gè)組件的當(dāng)前副本,直到指定的時(shí)間為止。它在HTTP響應(yīng)中發(fā)送。
缺點(diǎn):因?yàn)镋xpires頭使用一個(gè)特定的時(shí)間,它要求服務(wù)器和客戶端的時(shí)鐘嚴(yán)格同步。另外,過期日期需要經(jīng)常檢查,并且一旦這一天到來,還需要在服務(wù)器配置中提供一個(gè)新的日期。
圖片可緩存30天以上。
樣式表可緩存30天以上。
腳本可緩存30天以上。
b. Max-Age和mod_expires
HTTP1.1引入了Cache-Control頭來克服Expires頭的限制。Cache-Control使用max-age指令指定組件被緩存多久。它以秒為單位定義了一個(gè)更新窗。如果從組件被請(qǐng)求開始過去的秒數(shù)少于max-age,瀏覽器就使用緩存的版本,這就避免了額外的HTTP請(qǐng)求。如果同時(shí)出現(xiàn)Expires頭和Cache-Control max-age,max-age指令將重寫Exipres頭。
mod_expires Apache模塊,能夠讓Expires頭像max-age那樣以相對(duì)的方式設(shè)置日期。這通過ExpiresDefault指令來完成。
c. 空緩存VS完整緩存
指的是與頁面相關(guān)的瀏覽器緩存的狀態(tài)。
d. 修改文件名
為了確保用戶能夠獲取組件的最新版本,需要在所有HTML頁面中修改組件的文件名。嵌入版本號(hào)即可。
4. 壓縮組件
a. 通過減小HTTP響應(yīng)的大小來減少響應(yīng)時(shí)間。
b. 從HTTP1.1開始,Web客戶端可以通過HTTP請(qǐng)求中的Accept-Encoding頭來標(biāo)識(shí)對(duì)壓縮的支持。 Accept-Encoding:gzip,deflate。 如果Web服務(wù)器看到請(qǐng)求中有這個(gè)頭,就會(huì)使用客戶端列出來的方法中的一種來壓縮響應(yīng)。Web服務(wù)器通過響應(yīng)中的Content-Encoding頭來通知Web客戶端,如:Content-Encoding: gzip。
c. 網(wǎng)站會(huì)壓縮其HTML文檔、腳本和樣式表等。圖片和PDF不應(yīng)該壓縮,因?yàn)樗麄儽緛砭鸵呀?jīng)被壓縮了。試圖對(duì)它們進(jìn)行壓縮只會(huì)浪費(fèi)CPU資源,還有可能會(huì)增加文件大小。
d. 壓縮的成本有,服務(wù)器端會(huì)花費(fèi)額外的CPU周期來完成壓縮,客戶端要對(duì)壓縮文件進(jìn)行解壓縮。要檢測(cè)收益是否大于開銷,需要考慮響應(yīng)的大小、連接的帶寬和客戶端與服務(wù)器之間的Internet距離。
e. 代理緩存。在Web服務(wù)器的相應(yīng)中添加Vary頭。Web服務(wù)器可以告訴代理根據(jù)一個(gè)或多個(gè)請(qǐng)求頭來改變緩存的響應(yīng)。由于壓縮的決定是基于Accept-Encoding請(qǐng)求頭的,因此需要在服務(wù)器的Vary響應(yīng)頭中包含Accept-Encoding。Vary:Accept-Encoding。
f. 如果擁有大量的、多變的用戶群,能夠應(yīng)付較高的帶寬開銷,并且享有高質(zhì)量的名聲,請(qǐng)壓縮內(nèi)容并使用Cache-Control:Private。這禁用了代理,但避免了邊緣情形缺陷。
5. 將樣式表放在頂部
a. 盡量多使用link標(biāo)簽,少使用@import標(biāo)簽。因?yàn)锧import標(biāo)簽規(guī)則必須放在其他規(guī)則之前,也有可能會(huì)導(dǎo)致白屏現(xiàn)象,即使把@import規(guī)則放在文檔的HEAD標(biāo)簽中也是如此。
6. 將腳本放在底部
a. 在下載腳本時(shí)并行下載實(shí)際上是被禁用的——即使使用了不同的主機(jī)名,瀏覽器也不會(huì)啟動(dòng)其他的下載。其中一個(gè)原因是,腳本可能使用document.write來修改頁面內(nèi)容,因此瀏覽器會(huì)等待,以確保頁面能夠恰當(dāng)?shù)夭季帧A硗庖粋€(gè)原因是,為了保證腳本能夠按照正確的順序執(zhí)行。
b. 腳本對(duì)Web頁面的影響:腳本會(huì)阻塞對(duì)其后面內(nèi)容的呈現(xiàn),以及腳本會(huì)阻塞對(duì)其后面組件的下載。
//以下規(guī)則用于處理頁面加載之后的性能問題。
7. 避免CSS表達(dá)式
//min-width的兼容性
width:expression(document.body.clientWidth<600?”600px”:”auto”); //IE
min-width:600px; //大部分瀏覽器
存在問題:更新表達(dá)式
a. 一次性表達(dá)式,在這一次執(zhí)行中重寫它自身。
b. 事件處理器。
8. 使用外部JavaScript和CSS
純粹而言,內(nèi)聯(lián)快一些。但現(xiàn)實(shí)中還是使用外部文件會(huì)產(chǎn)生較快的頁面。因?yàn)镴avaScript和CSS文件有機(jī)會(huì)被瀏覽器緩存起來。HTML文檔通常不會(huì)被配置為可以緩存。另外,由于外聯(lián),HTML文檔減小,HTTP請(qǐng)求的數(shù)量也不會(huì)增加。
9. 減少DNS查找
a. DNS緩存和TTL(Time-to-live)
DNS查找可以被緩存起來提高性能。服務(wù)器可以表明記錄可以被緩存多久。查找返回的DNS記錄包含了一個(gè)存活時(shí)間TTL值。該值告訴客戶端可以對(duì)該記錄緩存多久。盡管操作系統(tǒng)緩存會(huì)考慮TTL值,但瀏覽器通常忽略該值,并設(shè)置它自己的時(shí)間限制。
10. 精簡JavaScript
a. 精簡是從代碼中移除不必要的字符以減小其大小,進(jìn)而改善加載時(shí)間的實(shí)踐。
b. 壓縮,并建議使用gzip來完成壓縮。
c. 精簡CSS。通常CSS中的注釋和空白比JavaScript少。優(yōu)化CSS——合并相同的類、移除不使用的類等。
11. 避免重定向
a. 重定向用與將用戶從一個(gè)URL重新路由到另一個(gè)URL。
b. 304并不是真的重定向——它用來響應(yīng)條件GET請(qǐng)求,避免下載已經(jīng)存在于瀏覽器緩存中的數(shù)據(jù)。
c. 狀態(tài)碼301和302是使用得最多的。狀態(tài)碼303和307是在HTTP1.1規(guī)范中添加的。但是幾乎沒有人用303和307,絕大多數(shù)網(wǎng)站仍然在沿用302.301響應(yīng)的示例如下:
HTTP 1.1 301 Moved Permanently
Location: https://stevesouders.com/newuri
Content-Type: text/html
瀏覽器會(huì)自動(dòng)將用戶帶到Location字段所給出的URL,響應(yīng)體通常是空的。不管叫什么名字,301和302響應(yīng)在實(shí)際中都不會(huì)被緩存,除非有附加的頭——如Expires或Cache-Control等要求它這么做。
d. 重定向延遲了整個(gè)HTML文檔的傳輸,在HTML文檔到達(dá)之前,頁面中不會(huì)呈現(xiàn)出任何東西,也沒人有任何組件會(huì)被下載。在用戶和HTML文檔之間插入重定向延遲了頁面中的所有東西。
e. 當(dāng)缺少結(jié)尾的斜線時(shí)發(fā)送重定向——它允許自動(dòng)索引,自動(dòng)轉(zhuǎn)到默認(rèn)的index.html上,并且能夠獲得與當(dāng)前目錄相關(guān)的URL。
12. 移除重復(fù)腳本
確保腳本只被包含一次。
13. 配置ETag
a. ETag(Entity Tag)實(shí)體標(biāo)簽是Web服務(wù)器和瀏覽器用于確認(rèn)緩存組件的有效性的一種機(jī)制。
b. ETag是HTTP1.1中引入的。ETag是唯一標(biāo)識(shí)了一個(gè)組件的一個(gè)特定版本的字符串。唯一的格式約束是該字符串必須用引號(hào)引起來。
c. ETag的加入為驗(yàn)證實(shí)體提供了比最新修改日期更為靈活的機(jī)制。
d. 例如,如果實(shí)體依據(jù)User-Agent或Accpt-Language頭而改變,實(shí)體的狀態(tài)可以反映到ETag中。此后,如果瀏覽器必須驗(yàn)證一個(gè)組件,它會(huì)使用If-None-Match頭將ETag傳回原始服務(wù)器。如果ETag是匹配的,就會(huì)返回304狀態(tài)碼,使響應(yīng)減小了1195字節(jié)。
14. 使Ajax可緩存
確保Ajax請(qǐng)求遵守性能知道,尤其應(yīng)具有長久的Expires頭。