Web優化躬行記(3)——影象和網路
一、影象
1)響應式影象
瀏覽器根據螢幕大小、裝置畫素比、橫豎屏自動載入合適的影象。
響應式的功能可以通過srcset和sizes兩個新屬性實現。
前者可指定選擇的影象以及其大小,後者會定義一組媒體條件並宣告填充的寬度。
在下面的示例中(線上檢視效果),瀏覽器會先檢視裝置寬度,然後檢查sizes列表中哪個媒體條件第一個為真,再檢視該媒體查詢的填充寬度,最後從載入的srcset列表中引用寬度最接近的影象。
<img srcset="elva-fairy-320w.jpg 320w, elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="elva-fairy-800w.jpg" />
2)懶載入
懶載入就是當滾動到頁面某個位置後,再顯示當前位置的影象,這樣做可以減少頁面請求。
預載入就是通過Image物件,給這個物件新增src屬性,以JavaScript的方式請求影象,並可以快取此物件,以後再用。
3)漸進載入
漸進載入是指先載入低質量甚至模糊的圖片,然後隨著頁面繼續載入,使用LQIP(低質量圖片佔位符)技術替換為高質量的完整版本。
這種技術確實提高了首次進行有意義繪製的時間。
4)壓縮
除了可通過剝離元資料(例如時間、地點等)的方式壓縮影象之外,還可以將影象畫到Canvas中,然後選擇質量輸出,從而實現壓縮。
5)雪碧圖
CSS Sprite是一種影象處理技術,將零散的小圖示整合在一起,形成成一張大圖,這張圖可稱為雪碧圖或精靈圖。
當用這張大圖做背景影象時,可以利用background-position屬性進行背景定位,找到想要的小圖示。
這麼處理影象,不但可以解決命名困擾,還能減少HTTP請求數,降低影象位元組,提升網頁效能。
參照下面的最佳實踐,可將雪碧圖優化得儘可能小:
1. 按照顏色合併。
2. 避免不必要的空白。
3. 將元素水平排列。
4. 將顏色限制在256種以內。
5. 先優化單獨的影象,再優化雪碧圖。
6. 通過控制大小和對齊減少反鋸齒畫素的數量。
7. 避免使用對角線漸變,這種漸變無法被平鋪。
6)WebP
WebP由Google引入,是一種支援有失真壓縮和無失真壓縮的圖片檔案格式,派生自影象編碼格式VP8。
根據Google的測試,無失真壓縮後的WebP比PNG檔案少了45%的檔案大小,即使這些PNG檔案經過其他壓縮工具壓縮之後,WebP還是可以減少28%的檔案大小。
WebP不支援像JPEG那樣的漸進式渲染,這導致使用者使用好的JPEG可能會更快地看到實際影象,儘管WebP影象的網路載入速度可能會更快。
7)icon font
圖示字型(icon font)就是將圖示做成字型,使用時與普通字型無異。
換成字型後,顏色、陰影、翻轉、大小和對齊等功能都能用CSS屬性控制,比影象靈活很多,並且縮放還不會失真,同時相容IE6,並且生成的檔案特別小。
使用font-display這個CSS屬性來控制字型的載入行為並使內容立即(font-display: optional)或幾乎立即(font-display: swap)可讀。
字型載入API用JavaScript來控制如何載入字型,提供了很大的自由度來決定如何將字型應用於文件。
document.fonts.load("1em Open Sans Light"); //載入字型 document.fonts.load("1em Open Sans Bold"); // 在所有指定的字型都載入後執行 document.fonts.ready.then(function(fontFaceSet) { });
二、網路
1)GZip壓縮
通過新增HTTP首部來向Web伺服器宣告支援壓縮。
Accept-Encoding: gzip, deflate
Web伺服器會返回一個經過壓縮的響應。
Content-Encoding: gzip
GZip對於要壓縮的檔案,首先使用LZ77演算法,然後對得到的結果再使用Huffman編碼的方法進行壓縮。
LZ77演算法過程如下:
1. 如果檔案中有兩塊內容相同的話,那麼只要知道前一塊的位置和大小,就可以確定後一塊的內容。
2. 可以用這樣一對資訊(兩者之間的距離,相同內容的長度),來替換後一塊內容。
3. 由於這一對資訊的大小,小於被替換內容的大小,所以檔案得到了壓縮。
Huffman編碼過程如下:
1. 把檔案中一定位長的值看作是符號,例如把8位長的256種值,也就是位元組的256種值看作是符號。
2. 根據這些符號在檔案中出現的頻率,對這些符號重新編碼。
3. 對於出現次數非常多的,用較少的位來表示,對於出現次數非常少的,用較多的位來表示。
4. 這樣一來,檔案的一些部分位數變少了,一些部分位數變多了。
5. 由於變小的部分比變大的部分多,所以整個檔案的大小還是會減小,檔案得到了壓縮。
2)Brotli壓縮
2015年,Google推出了Brotli,這是一種全新的開源無損資料格式,並被現在所有現代瀏覽器支援。
儘管Brotli在某些方面的效能與GZip相當,但它顯示出了良好的前景,並在不斷地發展中。
如果瀏覽器支援Brotli,那麼在請求首部中會將br令牌包含在可接受的編碼列表中。
Accept-Encoding: gzip, deflate, br
GZip的壓縮級別可指定0~9的整數來配置,而Brotli的範圍是0~11。
注意,使用Brotli壓縮所有資源非常耗費計算資源和時間,在最高壓縮級別下,會讓伺服器等待動態資源,伺服器開始傳送響應所花費的時間會抵消檔案大小減少帶來的任何潛在收益。
如果可以避開動態壓縮靜態資源的成本,那麼Brotli就是值得的。
Brotli可用於任何純文字的內容(HTML、CSS、SVG、JavaScript等),並且其效能相比GZip提高了17-25%。
3)DNS預讀取
DNS預讀取技術能夠加快開啟速度,方法是在head元素裡寫上幾個link元素。
<link rel="dns-prefetch" href="http://www.pwstrick.com"> <link rel="dns-prefetch" href="http://www.home602.com">
對以上幾個網站提前解析DNS,由於是並行的,也就不會阻塞頁面渲染。
4)快取
快取的處理過程可以簡單的分為幾步,首先在快取中搜索指定資源的副本,如果命中就執行第二步;第二步就是對資源副本進行新鮮度檢測(也就是文件是否過期),如果不新鮮就執行第三步;第三步是與伺服器進行再驗證,驗證通過(即沒有過期)就更新資源副本的新鮮度,再返回這個資源副本(此時的響應狀態碼為“304 Not Modified”),不通過就從伺服器返回資源,再將最新資源的副本放入快取中。
HTTP快取分為強快取和協商快取,前者的首部包括Cache-Control和Expires;後者會分為日期比對法(If-Modified-Since和Last-Modified)和實體標記法(If-None-Match和ETag)。
5)CDN
CDN是在使用者和伺服器之間增加Cache層,將使用者的訪問請求引導到Cache節點而不是伺服器源站點,要實現這一目的,主要是通過接管DNS實現。
CDN可以在全球分發各類資源,並根據地理位置、接入網型別(電信還是網通)將使用者的訪問請求定位到離使用者路由最短、位置最近、負載最輕的Cache節點(快取伺服器)上,實現就近定位,以此提升效能。
6)併發請求
瀏覽器的併發請求數目限制是針對同一域名的。
同一時間針對同一域名下的請求有一定數量限制(例如Chrome限制6條、IE11限制13條等),超過限制數目的請求會被阻塞。
所以將不同靜態資源(例如圖片、JavaScript、CSS等)放在不同的域名下,就能增加併發請求的數量。
7)HTTP/2.0
HTTP/2.0引入了全新的二進位制分幀層,解決了隊首阻塞問題,並且在一個域只需建立一次TCP連線,就能實現多路通訊,不必進行資源排隊,這樣就不需要雪碧圖或合併檔案了。
不僅如此,HTTP/2.0還有控制請求優先順序、伺服器主動推送和首部壓縮等優點,
8)API效能優化
在設計和開發API時,需要一個合理的協議來實現伺服器與第三方請求之間的通訊。
Restful API(REST)是一種廣泛驗證有效的選擇:它定義了一組約束,開發人員可以遵循這些約束以使內容以高效能,可靠和可伸縮的方式進行訪問。符合REST約束定義的Web服務稱為RESTful Web服務。
與普通的HTTP請求一樣,當從API檢索資料時,伺服器響應中的任何延遲都將傳播到終端使用者,從而影響渲染。如果許多資源都需要來自某個API的資料,則該API可能會成為效能瓶頸。GraphQL為這些問題提供了高效能的解決方案。
與REST不同,GraphQL可以在單個請求中檢索所有資料,並且只響應所需的內容,而不會像REST通常那樣過度或不足地獲取資料。
此外,因為GraphQL使用模式(Schema,定義資料結構的元資料),所以它可以提前將資料組織成所需的結構。因此在使用GraphQL後,就可以刪除用於處理狀態和資料結果的JavaScript程式碼,從而產生在客戶端上執行更快更乾淨的應用程式程式碼。
&n