爲何要作圖片優化?圖片優化的收益有多大?javascript
Google官方的最佳實踐中關於圖片優化有下面這樣一段描述:html
對於網頁來講,在所下載的字節數中,圖片每每會佔很大比例。所以,優化圖片一般能夠卓有成效地減小字節數和改進性能:瀏覽器須要下載的字節數越少,對客戶端帶寬的爭用就越少,瀏覽器下載內容並在屏幕上呈現內容的速度就越快。
那麼圖片到底佔多大比例?java
你們能夠看一下http archive這個網站,它統計了世界範圍內web資源的加載狀況等信息。
2017年11月15日到2018年11月15日,一年內總的 web 資源的平均請求體積:web
而關於圖片的體積:算法
圖片的體積大概佔總資源體積的37%,圖片在全部資源中佔比是很大的,爲此,咱們也很是有必要優化圖片的性能。瀏覽器
上面說的是全球網站的平均請求體積,下面咱們拿咱們本身的網上商城的網站看一下。緩存
這是咱們本身網站的首屏加載資源統計狀況,能夠看到圖片體積佔比更是達到了55.9%之高,這也很是符合電商網站的性質。(上圖結果是經過WebPageTest測試獲得)性能優化
咱們發現,圖片資源在網站全部資源中佔比很大,並且在電商類網站中佔比更大。優化圖片能夠減小客戶端下載的字節數,改進網頁性能。服務器
經常使用的web圖片格式有:JPEG/JPG、PNG、WebP、Base6四、SVGless
JPEG和JPG格式有什麼區別?
沒有區別,全名、正式擴展名是JPEG。但因DOS、Windows 95等早期系統採用的8.3命名規則只支持最長3字符的擴展名,爲了兼容採用了.jpg。也因歷史習慣和兼容性考慮,.jpg目前更流行。
JPEG/JPG
特色:有損壓縮、體積小、加載快、不支持透明
適用場景:適用於呈現色彩豐富的圖片,在咱們平常開發中,JPG 圖片常常做爲大的背景圖、輪播圖或 Banner 圖出現。
PNG
特色:無損壓縮、質量高、體積大、支持透明
適用場景:PNG 在處理線條和顏色對比度方面有優點,主要用它來呈現小的 Logo、顏色簡單且對比強烈的圖片或背景等。
SVG
特色:文本文件、體積小、不失真、兼容性好
適用場景:將 SVG 寫入獨立文件後引入 HTML
<img src="文件名.svg" alt="">
Base64
特色:文本文件、依賴編碼、小圖標解決方案
適用場景:小圖標,更新頻率很是低,做爲雪碧圖的補充
WebP
WebP 是 Google 專爲 Web 開發的一種旨在加快圖片加載速度的圖片格式,它支持有損壓縮和無損壓縮。
特色:全能但存在兼容性問題
使用場景:限制咱們使用 WebP 的最大問題不是「這個圖片是否適合用 WebP 呈現」,而是「瀏覽器是否容許 WebP」
WebP 的優點是它具備更優的圖像數據壓縮算法,能帶來更小的圖片體積,並且擁有肉眼識別無差別的圖像質量;同時具有了無損和有損的壓縮模式、Alpha 透明以及動畫的特性,在 JPEG 和 PNG 上的轉化效果都至關優秀、穩定和統一。
下左圖JPEG(1.6M) 下右圖WebP(1.2M)
cloudconvert能夠在線轉webp,你們能夠去試一下。
WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.
上文提到WebP雖然有諸多優點,但兼容性問題不得不考慮。在支持WebP的瀏覽器中優先使用WebP格式,不然採用默認格式。
看一下淘寶網站的作法,在Chrome瀏覽器下,採用的是WebP格式的圖片,在Safari瀏覽器下,採用的是JPEG格式的圖片。
看一下這兩張圖片的地址:
webp:https://img.alicdn.com/tfs/TB...
JPEG:https://img.alicdn.com/tfs/TB...
能夠發現,淘寶是根據是否支持webp,動態設置(字符串截斷)圖片url的。
如何判斷當前瀏覽器是否支持WebP?
能夠參考谷歌網站的作法。
// check_webp_feature: // 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'. // 'callback(feature, result)' will be passed back the detection result (in an asynchronous way!) function check_webp_feature(feature, callback) { var kTestImages = { lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA", lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==", alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==", animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA" }; var img = new Image(); img.onload = function () { var result = (img.width > 0) && (img.height > 0); callback(feature, result); }; img.onerror = function () { callback(feature, false); }; img.src = "data:image/webp;base64," + kTestImages[feature]; }
原理:對每一種格式的webp(有損,無損,alpha通道,動態)生成一個很小像素的圖片,在瀏覽器中渲染,若是沒有問題,就表明支持webp。
也可讓服務器端來判斷返回什麼格式的圖片,服務器根據 HTTP 請求頭部的 Accept 字段來決定返回什麼格式的圖片。當 Accept 字段包含 image/webp 時,就返回 WebP 格式的圖片,不然返回原圖。
利用SVGO壓縮svg文件的大小,下面這張SVG原圖80kb,利用SVGO壓縮後是23kb。
谷歌最佳實踐中指出:
對於靜態素材資源或不常變化的素材資源,咱們建議至少緩存 1 周,至多緩存 1 年。
如何使用緩存,有一張經典的圖能夠參考。
懶加載的原理是:將圖片的url賦值給img的data-url(可自定義)屬性,監聽滾動事件,當圖片進入可視區域時,將data-url的值賦值給img的url屬性,這時才真正發出圖片的http請求。具體實現能夠參考實現圖片懶加載
一種能夠在不一樣的屏幕尺寸和分辨率的設備上都能良好工做以及其餘特性的圖片
藝術方向:當你想爲不一樣佈局提供不一樣剪裁的圖片——好比在桌面佈局上顯示完整的、橫向圖片,而在手機佈局上顯示一張剪裁過的、突出重點的縱向圖片,能夠用 <picture> 元素來實現。
分辨率切換:當你想要爲窄屏提供更小的圖片時,由於小屏幕不須要像桌面端顯示那麼大的圖片;以及你想爲高/低分辨率屏幕提供不一樣分辨率的圖片時,均可以經過 vector graphics (SVG images)、 srcset 以及 sizes 屬性來實現。
<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" alt="Elva dressed as a fairy">
<img srcset="elva-fairy-320w.jpg, elva-fairy-480w.jpg 1.5x, elva-fairy-640w.jpg 2x" src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">
<picture> <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"> <source media="(min-width: 800px)" srcset="elva-800w.jpg"> <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> </picture>
性能優化須要瞭解其背後的原理,而後在項目中去實踐,才能真正掌握。
https://juejin.im/book/5b9365...
https://developers.google.com...
https://developers.google.com...
ps://httparchive.org/reports/page-weight#bytesTotal