性能優(yōu)化——圖片壓縮、加載和格式選擇
共 8845字,需瀏覽 18分鐘
·
2024-04-15 08:46
大廠技術(shù) 高級前端 Node進(jìn)階
點擊上方 程序員成長指北,關(guān)注公眾號
回復(fù)1,加入高級Node交流群
前言
相信大家都聽說過 "258 原則(https://blog.csdn.net/weixin_42139375/article/details/83001248)" ,一個網(wǎng)站的性能好壞很大程度上會影響到用戶的體驗。
在我經(jīng)歷的多個電商與大屏項目的優(yōu)化性能的項目后,我發(fā)現(xiàn)圖片資源的處理在網(wǎng)站性能優(yōu)化中有著舉足輕重的作用。
一般電商網(wǎng)站請求數(shù)據(jù)
在首屏加載的 145 個請求中圖片資源請求占到了 75% 以上,在所有請求靜態(tài)資源中圖片也占有著很大的比重。可見圖片優(yōu)化的重要性。
不過在認(rèn)識圖片優(yōu)化前我們先了解下二進(jìn)制位數(shù)與色彩呈現(xiàn)的關(guān)系。
二進(jìn)制位數(shù)與色彩
在計算機(jī)中,一般用二進(jìn)制數(shù)來表示像素。在不同的圖片格式中,像素與二進(jìn)制位數(shù)之間對應(yīng)的關(guān)系是不同的。一個像素對應(yīng)的二進(jìn)制位數(shù)越多,它能表示的顏色種類就豐富,成像效果也就越精致,圖片所需的存儲空間相應(yīng)也會越大。
目前市場上優(yōu)化圖片資源的方式有很多,如壓縮圖片、選擇正確格式、 CDN 加速、懶加載等。
壓縮圖片
壓縮圖片相信是大家第一時間想到的方案。像我們比較熟悉的 tinpng (https://tinypng.com/),他的原理是通過有"選擇性"地減少圖像所要存儲的顏色數(shù)量,來減少圖片所要存儲的內(nèi)存。
“When you upload a PNG (Portable Network Graphics) file, similar colors in your image are combined. This technique is called “quantization”. By reducing the number of colors, 24-bit PNG files can be converted to much smaller 8-bit indexed color images.
下面我們來看下樣例:
細(xì)節(jié)展示:
圖片格式
壓縮圖片雖然在一定程度上可以減少我們請求的資源所需要的帶寬,但如果是用對了格式在性能上往往會有質(zhì)的改變。
JPEG / JPG
JPEG 是最常用的圖像文件格式。
優(yōu)勢
-
支持極高的壓縮率,可使文件傳輸、下載、預(yù)覽速度大大加快。
-
利用可變的壓縮比可以控制文件大小。
-
能夠輕松地處理 1600 萬種顏色,可以很好地再現(xiàn)全彩色的圖像。
缺陷
JPG 的有損壓縮在輪播圖和背景圖的展示上確實很難看出破綻,但當(dāng)它處理矢量圖形和 Logo 等線條感較強(qiáng)、顏色對比強(qiáng)烈的圖像時,人為壓縮導(dǎo)致的圖片模糊會相當(dāng)明顯。因此不適宜用該格式來顯示高清晰度和線條感較強(qiáng)的圖像。
除此之外, JPG 并不支持對有透明度要求的圖像進(jìn)行顯示,如果需要顯示透明圖片還是需要另尋它路。
業(yè)務(wù)場景
JPG 適用于呈現(xiàn)色彩豐富的圖片,在我們?nèi)粘i_發(fā)中,JPG 圖片經(jīng)常作為大的背景圖、輪播圖或 預(yù)覽圖出現(xiàn)。打開某電商網(wǎng)站首頁,即可看到大圖片的處理幾乎都是使用了 JPG。
PNG - 8 與 PNG - 24
png 是一種采用無損壓縮算法的位圖格式。
優(yōu)勢
-
無損壓縮 -
完全支持 alpha 透明度。 -
可以重復(fù)保存且不降低圖像質(zhì)量。
缺點
體積太大
業(yè)務(wù)場景
理論上來說,當(dāng)你追求最佳的顯示效果(詳情展示圖、圖片有放大需求、攝影作品等),并且不在意存儲大小或所需帶寬時,可以使用 PNG-24 (https://baike.baidu.com/item/PNG/174154?fr=aladdin)。但實踐當(dāng)中,為了避免文件體積過大的問題,我們一般不用 PNG 去處理較復(fù)雜的圖像。當(dāng)我們遇到適合 PNG 的場景時,也會優(yōu)先選擇更為小巧的 PNG-8 。
亦或者需要處理有透明度或線條明顯的圖片時,也會采用 PNG 。如網(wǎng)站主 logo:
SVG
嚴(yán)格來說應(yīng)該是一種開放標(biāo)準(zhǔn)的矢量圖形語言。
優(yōu)點
-
可縮放,可支持無限放大 -
可編程
缺點
-
不是所有的瀏覽器都支持 SVG,IE8 和早期版本都需要一個插件。
-
復(fù)雜的圖片會降低渲染速度(只支持小圖)。
業(yè)務(wù)場景
SVG 是文本文件,我們既可以像寫代碼一樣定義 SVG ,把它寫在 HTML 里、成為 DOM 的一部分。用的比較多的就是 iconfont (https://www.iconfont.cn/)。我們可以通過設(shè)置模塊的 fill 屬性輕松適配圖標(biāo)的換膚功能,并通過 font-size 調(diào)節(jié)其大小。
Base64
一種基于 64 個可打印字符來表示二進(jìn)制數(shù)據(jù)的方法。
優(yōu)點
-
減少網(wǎng)絡(luò)請求 -
對于動態(tài)實時生成的圖片無需將圖片存儲在服務(wù)器占用服務(wù)器資源
缺點
-
只適于小圖。 -
若需要頻繁替換的圖片需要整個代碼替換,可維護(hù)性低。
業(yè)務(wù)場景
Base64 和雪碧圖一樣,是作為小圖標(biāo)解決方案而存在的。
“Base64 是一種用于傳輸 8Bit 字節(jié)碼的編碼方式,通過對圖片進(jìn)行 Base64 編碼,我們可以直接將編碼結(jié)果寫入 HTML 或者寫入 CSS ,從而減少 HTTP 請求的次數(shù)。
在 Elements 中搜索 “base64” 關(guān)鍵字,你會發(fā)現(xiàn) Base64 也有很多使用的地方。而且它對應(yīng)的圖片占用內(nèi)存較小。
既然 Base64 這么棒,我們把所有圖片都用Base64 好了嘛。
Base64 編碼后,圖片大小會膨脹為原文件的 4/3( Base64 編碼原理 (https://blog.csdn.net/wo541075754/article/details/81734770))。如果我們把大圖也編碼到 HTML 或 CSS 文件中,后者的體積會明顯增加,即便我們減少了 HTTP 請求,也無法彌補這龐大的體積帶來的性能開銷。也就是說我們犧牲的渲染性能大于資源請求性能,這樣做不太值得。
我們可以看到,大多數(shù)用 Base64 編碼的圖片都是小圖。
WebP
一種同時提供了有損壓縮與無損壓縮(可逆壓縮)的圖片文件格式。
優(yōu)點
-
支持有損無損
-
占用體積小
-
可支持透明
缺點
-
兼容性不好
業(yè)務(wù)場景
同 JPEG/JPG 。因為目前兼容性不好,一般搭配 JPEG/JPG 一起使用。
圖片格式小結(jié)
給大家整理了思維導(dǎo)圖:
OSS 搭配 CDN
我們原始的方式是將圖片等資源一起放入項目中打包上線。
這樣做的缺點在于打包出來的包大不說,用戶請求資源的速度也會受到限制。比如我們的服務(wù)器在華南,華北的用戶請求就會稍慢。當(dāng)遇到并發(fā)量大的情況時,從部署服務(wù)器請求接口與資源這無外乎給我們的服務(wù)器提供了多余的壓力。當(dāng)我們臨時想替換一張圖片時,也需要重新打包并發(fā)布上線,非常麻煩。
當(dāng)我們將圖片進(jìn)行 OSS 放置并 CDN 加速后,這個問題就得到了很好的解決。不同地區(qū)的用戶可以訪問就近服務(wù)器,重復(fù)的請求也會產(chǎn)生緩存,避免 OSS 流量的浪費。
《OSS 和 CDN 的區(qū)別》(https://www.cnblogs.com/jsfh/p/14076992.html) 大家也可以參考這篇文章進(jìn)行細(xì)看。
圖片的懶加載
相信大家一定會遇到首屏數(shù)據(jù)過多加載緩慢的情況。在這個情況下我們就需要考慮懶加載了。當(dāng)用戶滾動到預(yù)覽位置時,在進(jìn)行圖片數(shù)據(jù)的請求。期間用骨架屏或縮略圖代替。
window.onload = function () {
// 獲取圖片列表,即 img 標(biāo)簽列表
var imgs = document.querySelectorAll('img');
// 獲取到瀏覽器頂部的距離
function getTop(e) {
return e.offsetTop;
}
// 懶加載實現(xiàn)
function lazyload(imgs) {
// 可視區(qū)域高度
var h = window.innerHeight;
// 滾動區(qū)域高度
var s = document.documentElement.scrollTop || document.body.scrollTop;
for (var i = 0; i < imgs.length; i++) {
//圖片距離頂部的距離大于可視區(qū)域和滾動區(qū)域之和時懶加載
if ((h + s) > getTop(imgs[i])) {
// 真實情況是頁面開始有2秒空白,所以使用 setTimeout 定時 2s
(function (i) {
setTimeout(function () {
// 不加立即執(zhí)行函數(shù)i會等于9
// 隱形加載圖片或其他資源,
// 創(chuàng)建一個臨時圖片,這個圖片在內(nèi)存中不會到頁面上去。實現(xiàn)隱形加載
var temp = new Image();
temp.src = imgs[i].getAttribute('src');//只會請求一次
// onload 判斷圖片加載完畢,真是圖片加載完畢,再賦值給 dom 節(jié)點
temp.onload = function () {
// 獲取自定義屬性 src,用真圖片替換假圖片
imgs[i].src = imgs[i].getAttribute('src')
}
}, 2000)
})(i)
}
}
}
lazyload(imgs);
// 滾屏函數(shù)
window.onscroll = function () {
lazyload(imgs);
}
}
尾聲
性能優(yōu)化是我們前端開發(fā)工程師必須要掌握的一門硬技能。和學(xué)習(xí)其他新技術(shù)不同的是,當(dāng)你想學(xué)習(xí)一套新的框架時,閱讀文檔和源碼幾乎可以讓你在使用過程中游刃有余。但性能優(yōu)化卻不一樣,它只能讓我們?nèi)ッ魅ヮI(lǐng)悟去突破,它是一種經(jīng)驗也是一種習(xí)慣更是一種嗅覺。
參考資料
最佳實踐:使用阿里云 CDN 加速 OSS 訪問 (https://developer.aliyun.com/article/770616?utm_content=g_1000173381)
掘金小冊: 前端性能優(yōu)化原理與實踐 (https://juejin.cn/book/6844733750048210957)
壁紙網(wǎng)站: wellhaven (https://wallhaven.cc/)
最后
Node 社群
我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。
“分享、點贊、在看” 支持一下
