優化-瀏覽器快取和壓縮優化

m_nanle_xiaobudiu發表於2018-02-05

一、減少HTTP請求

1.圖片地圖:

假設導航欄上有五幅圖片,點選每張圖片都會進入一個連結,這樣五張導航的圖片在載入時會產生5個HTTP請求。然而,使用一個圖片地圖可以提高效率,這樣就只需要一個HTTP請求。

 

 

伺服器端圖片地圖:將所有點選提交到同一個url,同時提交使用者點選的x、y座標,伺服器端根據座標對映響應

客戶端圖片地圖:直接將點選對映到操作

<img src="planets.jpg" border="0" usemap="#planetmap" alt="Planets" />

<map name="planetmap" id="planetmap">
     <area shape="rect" coords="180,139,14" href ="venus.html" alt="Venus" />
     <area shape="rect" coords="129,161,10" href ="mercur.html" alt="Mercury" />
     <area shape="rect" coords="0,0,110,260" href ="sun.html" alt="Sun" />
     <area shape="rect" coords="140,0,110,260" href ="star.html" alt="Sun" />
</map>

使用圖片地圖的缺點:指定座標區域時,矩形或圓形比較容易指定,而其它形狀手工指定比較難

 

2.CSS Sprites

CSS Sprites直譯過來就是CSS精靈,但是這種翻譯顯然是不夠的,其實就是通過將多個圖片融合到一副圖裡面,然後通過CSS的一些技術佈局到網頁上。特別是圖片特別多的網站,如果能用css sprites降低圖片數量,帶來的將是速度的提升。

 

<div>
    <span id="image1" class="nav"></span>
    <span id="image2" class="nav"></span>
    <span id="image3" class="nav"></span>
    <span id="image4" class="nav"></span>
    <span id="image5" class="nav"></span>
</div>

 

.nav {
    width: 50px;
    height: 50px;
    display: inline-block;
    border: 1px solid #000;
    background-image: url('E:/1.png');
}
#image1 {
        background-position: 0 0;
}
#image2 {
        background-position: -95px 0;
}
#image3 {
        background-position: -185px 0;
}
#image4 {
        background-position: -275px 0;
}
#image5 {
        background-position: -366px -3px;
}

 

執行結果:

PS:使用CSS Sprites還有可能降低下載量,可能大家會認為合併後的圖片會比分離圖片的總和要大,因為還有可能會附加空白區域。實際上,合併後的圖片會比分離的圖片總和要小,因為它降低了圖片自身的開銷,譬如顏色表、格式資訊等。

 

3.字型圖示

在可以大量使用字型圖示的地方我們可以儘可能使用字型圖示,字型圖示可以減少很多圖片的使用,從而減少http請求,字型圖示還可以通過CSS來設定顏色、大小等樣式,何樂而不為。

 

4.合併js和css

將多個樣式表或者指令碼檔案合併到一個檔案中,可以減少HTTP請求的數量從而縮短效應時間。

然而合併所有檔案對許多人尤其是編寫模組化程式碼的人來說是不能忍的,而且合併所有的樣式檔案或者指令碼檔案可能會導致在一個頁面載入時載入了多於自己所需要的樣式或者指令碼,對於只訪問該網站一個(或幾個)頁面的人來說反而增加了下載量,所以大家應該自己權衡利弊。

 

二、使用CDN

如果應用程式web伺服器離使用者更近,那麼一個HTTP請求的響應時間將縮短。另一方面,如果元件web伺服器離使用者更近,則多個HTTP請求的響應時間將縮短。

CDN(內容釋出網路)是一組分佈在多個不同地理位置的Web伺服器,用於更加有效地向使用者釋出內容。在優化效能時,向特定使用者釋出內容的伺服器的選擇基於對網路慕課擁堵的測量。例如,CDN可能選擇網路階躍數最小的伺服器,或者具有最短響應時間的伺服器。

CDN還可以進行資料備份、擴充套件儲存能力,進行快取,同時有助於緩和Web流量峰值壓力。

CDN的缺點:

1、響應時間可能會受到其他網站流量的影響。CDN服務提供商在其所有客戶之間共享Web伺服器組。

2、如果CDN服務質量下降了,那麼你的工作質量也將下降

3、無法直接控制元件伺服器

 

三、新增Expires頭

頁面的初次訪問者會進行很多HTTP請求,但是通過使用一個長久的Expires頭,可以使這些元件被快取,下次訪問的時候,就可以減少不必要的HTPP請求,從而提高載入速度。

Web伺服器通過Expires頭告訴客戶端可以使用一個元件的當前副本,直到指定的時間為止。例如:

Expires: Fri, 18 Mar 2016 07:41:53 GMT

Expires缺點: 它要求伺服器和客戶端時鐘嚴格同步;過期日期需要經常檢查

HTTP1.1中引入Cache-Control來克服Expires頭的限制,使用max-age指定元件被快取多久。

Cache-Control: max-age=12345600

若同時制定Cache-Control和Expires,則max-age將覆蓋Expires頭

 

四、壓縮元件

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

Accept-Encoding: gzip,deflate

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

Content-Encoding: gzip

代理快取

當瀏覽器通過代理來傳送請求時,情況會不一樣。假設針對某個URL傳送到代理的第一個請求來自於一個不支援gzip的瀏覽器。這是代理的第一個請求,快取為空。代理將請求轉發給伺服器。此時響應是未壓縮的,代理快取同時傳送給瀏覽器。現在,假設到達代理的請求是同一個url,來自於一個支援gzip的瀏覽器。代理會使用快取中未壓縮的內容進行響應,從而失去了壓縮的機會。相反,如果第一個瀏覽器支援gzip,第二個不支援,你們代理快取中的壓縮版本將會提供給後續的瀏覽器,而不管它們是否支援gzip。

解決辦法:在web伺服器的響應中新增vary頭Web伺服器可以告訴代理根據一個或多個請求頭來改變快取的響應。因為壓縮的決定是基於Accept-Encoding請求頭的,因此需要在vary響應頭中包含Accept-Encoding。

  vary: Accept-Encoding

 

五、將樣式表放在頭部

首先說明一下,將樣式表放在頭部對於實際頁面載入的時間並不能造成太大影響,但是這會減少頁面首屏出現的時間,使頁面內容逐步呈現,改善使用者體驗,防止“白屏”。

我們總是希望頁面能夠儘快顯示內容,為使用者提供視覺化的回饋,這對網速慢的使用者來說是很重要的。

將樣式表放在文件底部會阻止瀏覽器中的內容逐步出現。為了避免當樣式變化時重繪頁面元素,瀏覽器會阻塞內容逐步呈現,造成“白屏”。這源自瀏覽器的行為:如果樣式表仍在載入,構建呈現樹就是一種浪費,因為所有樣式表載入解析完畢之前務虛會之任何東西

 

六、將指令碼放在底部

跟樣式表相同,指令碼放在底部對於實際頁面載入的時間並不能造成太大影響,但是這會減少頁面首屏出現的時間,使頁面內容逐步呈現。

js的下載和執行會阻塞Dom樹的構建(嚴謹地說是中斷了Dom樹的更新),所以script標籤放在首屏範圍內的HTML程式碼段裡會截斷首屏的內容。

下載指令碼時並行下載是被禁用的——即使使用了不同的主機名,也不會啟用其他的下載。因為指令碼可能修改頁面內容,因此瀏覽器會等待;另外,也是為了保證指令碼能夠按照正確的順序執行,因為後面的指令碼可能與前面的指令碼存在依賴關係,不按照順序執行可能會產生錯誤。

 

七、使用外部的JavaScript和CSS

內聯指令碼或者樣式可以減少HTTP請求,按理來說可以提高頁面載入的速度。然而在實際情況中,當指令碼或者樣式是從外部引入的檔案,瀏覽器就有可能快取它們,從而在以後載入的時候能夠直接使用快取,而HTML文件的大小減小,從而提高載入速度。

影響因素:

1、每個使用者產生的頁面瀏覽量越少,內聯指令碼和樣式的論據越強勢。譬如一個使用者每個月只訪問你的網站一兩次,那麼這種情況下內聯將會更好。而如果該使用者能夠產生很多頁面瀏覽量,那麼快取的樣式和指令碼將會極大減少下載的時間,提交頁面載入速度。

2、如果你的網站不同的頁面之間使用的元件大致相同,那麼使用外部檔案可以提高這些元件的重用率。

 

 

八、減少DNS查詢

當我們在瀏覽器的位址列輸入網址(譬如: www.linux178.com) ,然後回車,回車這一瞬間到看到頁面到底發生了什麼呢?

域名解析 --> 發起TCP的3次握手 --> 建立TCP連線後發起http請求 --> 伺服器響應http請求,瀏覽器得到html程式碼 --> 瀏覽器解析html程式碼,並請求html程式碼中的資源(如js、css、圖片等) --> 瀏覽器對頁面進行渲染呈現給使用者。

DNS也是開銷,通常瀏覽器查詢一個給定域名的IP地址要花費20~120毫秒,在完成域名解析之前,瀏覽器不能從伺服器載入到任何東西。那麼如何減少域名解析時間,加快頁面載入速度呢?

當客戶端DNS快取(瀏覽器和作業系統)快取為空時,DNS查詢的數量與要載入的Web頁面中唯一主機名的數量相同,包括頁面URL、指令碼、樣式表、圖片、Flash物件等的主機名。減少主機名的 數量就可以減少DNS查詢的數量。

減少唯一主機名的數量會潛在減少頁面中並行下載的數量(HTTP 1.1規範建議從每個主機名並行下載兩個元件,但實際上可以多個),這樣減少主機名和並行下載的方案會產生矛盾,需要大家自己權衡。建議將元件放到至少兩個但不多於4個主機名下,減少DNS查詢的同時也允許高度並行下載。

 

九、精簡JavaScript

精簡

精簡就是從程式碼中移除不必要的字元以減少檔案大小,降低載入的時間。程式碼精簡的時候會移除不必要的空白字元(空格,換行、製表符),這樣整個檔案的大小就變小了。

網上有很多線上壓縮,可以嘗試一下。

在以上提到了關於用gzip之類的壓縮方式來壓縮檔案,這邊說明一下,就算使用gzip等方式來壓縮檔案,精簡程式碼依然是有必要的。一般來說,壓縮產生的節省是高於精簡的,在生產環境中,精簡和壓縮同時使用能夠最大限度的獲得更多的節省。

 

十、避免重定向

什麼是重定向?

重定向用於將使用者從一個URL重新路由到另一個URL。

常用重定向的型別

301:永久重定向,主要用於當網站的域名發生變更之後,告訴搜尋引擎域名已經變更了,應該把舊域名的的資料和連結數轉移到新域名下,從而不會讓網站的排名因域名變更而受到影響。

302:臨時重定向,主要實現post請求後告知瀏覽器轉移到新的URL。

304:Not Modified,主要用於當瀏覽器在其快取中保留了元件的一個副本,同時元件已經過期了,這是瀏覽器就會生成一個條件GET請求,如果伺服器的元件並沒有修改過,則會返回304狀態碼,同時不攜帶主體,告知瀏覽器可以重用這個副本,減少響應大小。

 

重定向如何損傷效能?

當頁面發生了重定向,就會延遲整個HTML文件的傳輸。在HTML文件到達之前,頁面中不會呈現任何東西,也沒有任何元件會被下載。

來看一個實際例子:對於ASP.NET webform開發來說,對於新手很容易犯一個錯誤,就是把頁面的連線寫成伺服器控制元件後臺程式碼裡,例如用一個Button控制元件,在它的後臺click事件中寫上:Response.Redirect("");然而這個Button的作用只是轉移URL,這是非常低效的做法,因為點選Button後,先傳送一個Post請求給伺服器,伺服器處理Response.Redirect("")後就傳送一個302響應給瀏覽器,瀏覽器再根據響應的URL傳送GET請求。正確的做法應該是在html頁面直接使用a標籤做連結,這樣就避免了多餘的post和重定向。

 

重定向的應用場景

1. 跟蹤內部流量

重定向經常用於跟蹤使用者流量的方向,當擁有一個門戶主頁的時候,同時想對使用者離開主頁後的流量進行跟蹤,這時可以使用重定向。例如: 某網站主頁新聞的連結地址http://a.com/r/news,點選該連結將產生301響應,其Location被設定為http://news.a.com。通過分析a.com的web伺服器日誌可以得知人們離開首頁之後的去向。

我們知道重定向是如何損傷效能的,為了實現更好的效率,可以使用Referer日誌來跟蹤內部流量去向。每個HTTP請求都有一個Referer表示原始請求頁(除了從書籤開啟或直接鍵入URL等操作),記錄下每個請求的Referer,就避免了向使用者傳送重定向,從而改善了響應時間。

 

2. 跟蹤出站流量

有時連結可能將使用者帶離你的網站,在這種情況下,使用Referer就不太現實了。

同樣也可以使用重定向來解決跟蹤出站流量問題。以百度搜尋為例,百度通過將每個連結包裝到一個302重定向來解決跟蹤的問題,例如搜尋關鍵字“前端效能優化”,搜尋結果中的一個URL為https://www.baidu.com/link?url=pDjwTfa0IAf_FRBNlw1qLDtQ27YBujWp9jPN4q0QSJdNtGtDBK3ja3jyyN2CgxR5aTAywG4SI6V1NypkSyLISWjiFuFQDinhpVn4QE-uLGG&wd=&eqid=9c02bd21001c69170000000556ece297,即使搜尋結果並沒有變,但這個字串是動態改變的,暫時還不知道這裡起到怎樣的作用?(個人感覺:字串中包含了待訪問的網址,點選之後會產生302重定向,將頁面轉到目標頁面(待修改,求大神們給我指正))

除了重定向外,我們還可以選擇使用信標(beacon)——一個HTTP請求,其URL中包含有跟蹤資訊。跟蹤資訊可以從信標Web伺服器的訪問日記中提取出來,信標通常是一個1px*1px的透明圖片,不過204響應更優秀,因為它更小,從來不被快取,而且絕不會改變瀏覽器的狀態。

 

十一、刪除重複指令碼

在團隊開發一個專案時,由於不同開發者之間都可能會向頁面中新增頁面或元件,因此可能相同的指令碼會被新增多次。

重複的指令碼會造成不必要的HTTP請求(如果沒有快取該指令碼的話),並且執行多餘的JavaScript浪費時間,還有可能造成錯誤。

 

十二、使Ajax可快取

 

非同步與即時

Ajax的一個明顯的有點就是向使用者提供了即時反饋,因為它非同步的從後端web伺服器請求資訊。

使用者是否需要等待的關鍵因素在於Ajax請求是被動的還是主動的。被動請求是為了將來來使用而預先發起的,主動請求是基於使用者當前的操作而發起的

什麼樣的AJAX請求可以被快取?

POST的請求,是不可以在客戶端快取的,每次請求都需要傳送給伺服器進行處理,每次都會返回狀態碼200。(可以在伺服器端對資料進行快取,以便提高處理速度)

GET的請求,是可以(而且預設)在客戶端進行快取的,除非指定了不同的地址,否則同一個地址的AJAX請求,不會重複在伺服器執行,而是返回304。

Ajax請求使用快取

在進行Ajax請求的時候,可以選擇儘量使用get方法,這樣可以使用客戶端的快取,提高請求速度。

 

如果是原創文章,轉載請註明出處:http://www.cnblogs.com/MarcoHan

相關文章