** 性能黃金法則 **
只有10%20%的最終用戶響應(yīng)時間花在了下載HTML文檔上。其余的80%90%時間花在了下載頁面中的所有組件上。
** 前端處理規(guī)則 **
- 減少HTTP請求
- 使用內(nèi)容發(fā)布網(wǎng)絡(luò)
- 添加Expires頭
- 壓縮組件
- 將樣式表放在頂部
- 將腳本放在底部
- 避免CSS表達式
- 使用外部JavaScript和CSS
- 減少DNS查找
- 精簡JavaScript
- 避免重定向
- 移除重復(fù)腳本
- 配置ETag
- 使Ajax可緩存
HTTP相關(guān)概念
- HTTP請求類型:
GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE
- 壓縮:
瀏覽器使用Accept-Encoding頭來聲明支持壓縮:Accept-Encoding:gzip,deflate
服務(wù)器使用Content-Encoding頭確認響應(yīng)已被壓縮:Content-Encoding:gzip - 條件GET請求:瀏覽器在緩存中保存了一個組件的副本,當If-Modified-Since頭詢問組件副本是否可用,服務(wù)器若返回304響應(yīng),瀏覽器得到一個更小更快的響應(yīng)(沒有響應(yīng)體)。
- Expires:Expires:Wed,05 Oct 2016 19:16:20 GMT
Expires頭明確指出瀏覽器是否可以使用組件副本。瀏覽器將過期時間和組件副本一同存入緩存,不再詢問服務(wù)器組件副本是否可用。 - Keep-Alive:瀏覽器和服務(wù)器均使用Connection:keep-alive頭指出對Keep-Alive的支持。
瀏覽器或服務(wù)器通過發(fā)出Connection:close關(guān)閉連接。
注:在HTTP1.1中定義的管道技術(shù)普及之前,Keep-Alive依然是必要手段。對于HTTPS來說更重要,因為建立新的安全socket連接需要更多時間。
規(guī)則筆記
規(guī)則1.減少HTTP請求
技術(shù):圖片地圖、CSS Sprites、內(nèi)聯(lián)圖片和腳本、樣式表的合并。
【圖片地圖】
圖片地圖(Image Map):將多個帶有鏈接的圖片合并為一張圖片,通過圖片地圖,點擊不同位置鏈接到不同位置。
分類:服務(wù)器端圖片地圖&客戶端圖片地圖(常用)
示例代碼(客戶端):
<img usemap="#map1" src="/img/example.png">
<map name="map1">
<area shape="rect" coords="0,0,31,31" href="location1" title="ToLocation1">
<area shape="rect" coords="0,12,121,213" href="location2" title="ToLocation2">
……
<area shape="rect" coords="141,0,171,31" href="locationN" title="ToLocationN">
</map>
缺點:
- 手工完成困難容易出錯
- 除了矩形之外幾乎無法定義其他形狀
- 通過DHML創(chuàng)建的圖片地圖無法再IE中工作
【CSS Sprites】
即雪碧圖。將多個圖片合并成一張圖片,通過background-position控制顯示。
【內(nèi)聯(lián)圖片】
使用data:URL模式可以在Web頁面中包含圖片但無需任何的HTTP請求。
常見的URl模式:http:、ftp:、file:、mailto:、smtp:、pop:、dns:、whois:、finger:、daytime:、news:、urn:。
data:URL模式格式:
data:[<mediatype>][;base64],<data>
data一般被用于內(nèi)聯(lián)圖片,但它可以用在任何指定URL的地方。
注:不要內(nèi)聯(lián)公司logo。做法:CSS將內(nèi)聯(lián)圖片作為背景,將CSS放在外部樣式表中(達到瀏覽器緩存功能)。
經(jīng)驗:普通圖片就不要采用內(nèi)聯(lián)圖片了,數(shù)據(jù)量巨大,嚴重增大HTML文檔的大小。
【合并腳本和樣式表】
規(guī)則2.使用內(nèi)容發(fā)布網(wǎng)絡(luò)
- 在多個地理位置不同的服務(wù)器上部署內(nèi)容
- 實現(xiàn)地理位置分離的第一步,不要嘗試使用分布式架構(gòu)重新設(shè)計你的應(yīng)用程序
- 使用CDN(缺點:CDN服務(wù)掛掉將直接影響應(yīng)用,不可控因素;解決方法:使用多家CDN服務(wù))
- 測試CDN服務(wù)的效果和測試所在地理位置有關(guān)
- 有助于完成測試的兩個網(wǎng)站:Keynote System(www.keynote.com)和Gomez(www.gomez.com)
規(guī)則3.添加Expires頭
在這一日期/時間之后,響應(yīng)將被認為是無效的。
- HTTP1.1引入Cache-Control頭克服Expires頭限制(要求服務(wù)器客戶端的始終嚴格同步,還需要配置維護)
Cache-Control:max-age:315360000
注:時間單位為秒
- mod_expires Apache模塊使你在使用Expires頭時能夠像max-age那樣以相對的方式設(shè)置時間。
注:此部分示例代碼由于和MarkDown沖突會顯示錯誤,詳細內(nèi)容請自行查詢資料
【空緩存VS完整緩存】
使用長久的Expires頭
【修訂文件名】
為使用戶獲取更新,將組件的文件名加上版本號。更新文件時修改文件版本號將會使用戶重新從服務(wù)器上獲取組件。
規(guī)則4.壓縮組件
減小頁面大小的方法:
- 壓縮HTTP響應(yīng)包(效果最顯著)
- 刪除注釋
- 縮短URL
- Web客戶端通過HTTP請求中的Accept-Encoding頭來標識對壓縮的支持
Accept-Encoding:gzip,default
- Web服務(wù)器通過客戶端列出方法中的一種來壓縮響應(yīng)。
- gzip是最理想的壓縮方式。
- 需要壓縮的內(nèi)容:HTML文檔、腳本、樣式表、XML和JSON在內(nèi)的任何文本響應(yīng)。
- 不應(yīng)該壓縮的內(nèi)容:圖片和PDF(浪費CPU,增加大小)
- 壓縮成本:服務(wù)器CPU開銷和客戶端解壓縮耗費的資源
- 檢測收益是否大于開銷需要考慮的因素:響應(yīng)的大小,連接的帶寬,客戶端與服務(wù)端Internet距離
- 根據(jù)經(jīng)驗,通常對大于1KB或2KB的文件進行壓縮
- mod_gzip_mininum_file_size控制著希望壓縮文件的最小值,默認為500B
【代理緩存】
存在兩種方式上的問題:
問題1:
不支持gzip的瀏覽器先訪問了代理服務(wù)器,代理服務(wù)器轉(zhuǎn)發(fā)請求,服務(wù)器返回未經(jīng)壓縮的響應(yīng)包給代理服務(wù)器,代理服務(wù)器將未經(jīng)壓縮的響應(yīng)包緩存后轉(zhuǎn)發(fā)給該瀏覽器;
支持gzip的瀏覽器請求代理服務(wù)器,代理服務(wù)器發(fā)現(xiàn)緩存,直接將緩存的未經(jīng)壓縮的響應(yīng)包返回給該支持gzip的瀏覽器。
結(jié)果:雖然支持gzip的瀏覽器收到的是未經(jīng)壓縮的響應(yīng)包,未提高效率,但最終還能完成基本的請求。
問題2:
支持gizp的瀏覽器先訪問了代理服務(wù)器,代理服務(wù)器轉(zhuǎn)發(fā)請求,服務(wù)器返回經(jīng)過壓縮的響應(yīng)包給代理服務(wù)器,代理服務(wù)器將經(jīng)過壓縮的響應(yīng)包緩存后轉(zhuǎn)發(fā)給該瀏覽器;
不支持gzip的瀏覽器請求代理服務(wù)器,代理服務(wù)器發(fā)現(xiàn)緩存,直接將緩存的經(jīng)過壓縮的響應(yīng)包返回給該不支持gzip的瀏覽器。
結(jié)果:第二個不支持gzip的瀏覽器收到的是經(jīng)過壓縮的響應(yīng)包,無法正常解析。
解決方法:在Web服務(wù)器中添加Vary頭
Vary:Accept-Encoding
規(guī)則5.將樣式表放在頂部
違反規(guī)則將樣式表放在頂部或HEAD標簽外,雖然不影響加載組件的時間,但會影響文檔呈現(xiàn)效果,這有不同的瀏覽器決定(白屏或無樣式內(nèi)容閃爍)。
規(guī)則6.將腳本放在底部
規(guī)則7.避免CSS表達式
規(guī)則8.使用外部的JavaScript和CSS
如果要實現(xiàn)主頁快速訪問且后續(xù)網(wǎng)頁也能較快使用組件,可以這樣:
1.在主頁加載完成后下載后續(xù)網(wǎng)頁所需組件(加載后下載)
2.動態(tài)內(nèi)聯(lián)(利用Cookie作指示器,如果有緩存,則生成一個使用外鏈組件的主頁,并在主頁加載完成后下載后續(xù)組件;如果沒有緩存,則生成一個使用內(nèi)聯(lián)組件的主頁,同樣在加載完成后下載后續(xù)組件)
規(guī)則9.減少DNS查找
當客戶端的DNS緩存為空(瀏覽器和操作系統(tǒng)都是)時,DNS查找的數(shù)量與Web頁面中唯一主機名的數(shù)量相等。
建議:將組件分別放到2~4個主機名下(減少主機名潛在減少了組件并行下載的數(shù)量)。
規(guī)則10.精簡JavaScript
從代碼中移除不必要的字符,包含注釋、不必要的空白字符(空格、換行和制表符)
【混淆】
精簡 + 改寫函數(shù)和變量名
通常目標:增加反向工程難度
缺點:
- 缺陷:由于混淆更加復(fù)雜,混淆過程本身很可能引入錯誤。
- 維護:由于混淆會改變JavaScript符號,因此需要對任何不能改變的符號(例如API函數(shù))進行標記,防止混淆修改它們。
- 經(jīng)過混淆的代碼很難閱讀。這使得在產(chǎn)品環(huán)境調(diào)試問題更加困難。
精簡JavaScript的工具:JSMin和DojoCompressor(ShrinkSafe)
【精簡CSS】
收益通常小于精簡JavaScript
優(yōu)化CSS:
- 合并相同的類、移除不使用的類
- 移除注釋和空白
- 直觀優(yōu)化(如縮寫#606代替#660066)
- 移除不必要字符(例如0代替0px)
規(guī)則11.避免重定向
規(guī)則12.移除重復(fù)腳本
規(guī)則13.配置ETag
ETag是唯一標識了一個組件的一個特定的字符串。
- 唯一的格式約束是該字符串必須用引號引起來。
- 如果你無需自定義ETag,最好簡單地將其移除。
規(guī)則14.使Ajax可緩存
應(yīng)具有長久的Expires頭
此篇筆記是我閱讀《高性能網(wǎng)站建設(shè)指南》這篇文章記錄的筆記,寫出來與大家共享。
如果需要閱讀原文,請下載PDF文檔:《高性能網(wǎng)站建設(shè)指南》