選擇合適的圖片格式
JPEG
JPEG 是由 Joint Photographic Experts Group 所開發(fā)出的一種圖片前方。它最大的特點(diǎn)是?有損壓縮。這種高效的壓縮算法使它成為了一種非常輕巧的圖片格式憾朴。另一方面,即使被稱為“有損”壓縮,JPG 的壓縮方式仍然是一種高質(zhì)量的壓縮方式:當(dāng)我們把圖片體積壓縮至原有體積的 50% 以下時(shí)镜廉,JPG 仍然可以保持住 60% 的品質(zhì)签餐。此外寓涨,JPG 格式以 24 位存儲單個(gè)圖,可以呈現(xiàn)多達(dá) 1600 萬種顏色氯檐,足以應(yīng)對大多數(shù)場景下對色彩的要求缅茉,這一點(diǎn)決定了它壓縮前后的質(zhì)量損耗并不容易被我們?nèi)祟惖娜庋鬯煊X。
優(yōu)點(diǎn)
1.JPEG 格式的圖片可以呈現(xiàn)數(shù)百萬種顏色男摧。所以每當(dāng)網(wǎng)站需要呈現(xiàn)色彩豐富的圖片蔬墩,JPEG 總是最佳選擇。
2.有損壓縮耗拓,你可以通過壓縮大大的減少圖片的體積拇颅,一般圖片用 60%級別比較合適,如果選擇大于 75%的壓縮等級乔询,則會使圖片有明顯的質(zhì)量下降樟插。
3.無兼容性問題,所以開發(fā)者可以放心隨意使用。
使用場景
1.JPG 適用于呈現(xiàn)色彩豐富的圖片黄锤,在我們?nèi)粘i_發(fā)中搪缨,JPEG 圖片經(jīng)常作為大的背景圖、輪播圖或 Banner 圖出現(xiàn)鸵熟。
2.但是有損壓縮后的圖片確實(shí)很難露出馬腳副编,當(dāng)它處理矢量圖形和 Logo 等線條感較強(qiáng)、顏色對比強(qiáng)烈的圖像時(shí)流强,人為壓縮的圖片模糊會相當(dāng)明顯痹届。
3.JPEG 圖像不支持透明度處理,透明圖片可選擇使用 PNG打月。
PNG
PNG(可移植網(wǎng)絡(luò)圖形格式)是由 W3C 開發(fā)的圖片格式队腐,是一種無損壓縮的高保真的圖片格式。它同時(shí)支持 8 位和 24 位奏篙,這里都是二進(jìn)制數(shù)的位數(shù)柴淘。按照我們前置知識里提到的對應(yīng)關(guān)系,8 位的 PNG 最多支持 256 種顏色秘通,而 24 位的可以呈現(xiàn)約 1600 萬種顏色悠就。
PNG 圖片具有比 JPEG 更強(qiáng)的色彩表現(xiàn)力,對線條的處理更加細(xì)膩充易,對透明度有良好的支持梗脾。它彌補(bǔ)了上文我們提到的 JPEG 的局限性,唯一的缺點(diǎn)就是體積太大盹靴。
應(yīng)用場景
1.PNG 在處理線條和顏色對比度方面的優(yōu)勢炸茧,我們主要用它來呈現(xiàn)小的 Logo、顏色簡單且對比強(qiáng)烈的圖片或背景等稿静。
2.支持透明度處理梭冠,透明圖片可選擇使用 PNG
GIF
GIF 是一種最多支持 256 種顏色的 8 位無損圖片格式。這個(gè)限制讓 GIF 格式對于多顏色或者攝影圖片的展示無能為力改备。
優(yōu)點(diǎn)
1.支持 256 中顏色控漠,文件體積通常都很小
2.支持透明
應(yīng)用場景
支持動(dòng)畫,適合去展示一些無限循環(huán)的動(dòng)畫悬钳,比如圖標(biāo)盐捷、表情、廣告欄等默勾。
對于一些只有簡單色彩的圖片非常合適碉渡。
WebP
WebP 是一種同時(shí)提供了有損壓縮與無損壓縮(可逆壓縮)的圖片文件格式,派生自影像編碼格式 VP8母剥。它像 JPEG 一樣對細(xì)節(jié)豐富的圖片信手拈來滞诺,像 PNG 一樣支持透明形导,像 GIF 一樣可以顯示動(dòng)態(tài)圖片,集多種圖片文件格式的優(yōu)點(diǎn)于一身习霹。
WebP 最初在 2010 年發(fā)布朵耕,目標(biāo)是減少文件大小,但達(dá)到和 JPEG 格式相同的圖片質(zhì)量淋叶,希望能夠減少圖片檔在網(wǎng)絡(luò)上的發(fā)送時(shí)間阎曹。根據(jù) Google 較早的測試,WebP 的無損壓縮比網(wǎng)絡(luò)上找到的 PNG 檔少了 45%的文件大小爸吮,即使這些 PNG 檔在使用 pngcrush 和 PNGOUT 處理過芬膝,WebP 還是可以減少 28%的文件大小望门。
雖然 webP 有諸多優(yōu)點(diǎn)形娇,但是它不能完全替代 JPEG 和 PNG,因?yàn)闉g覽器對 WebP 支持并不普遍筹误。特別是移動(dòng)端 IOS 系統(tǒng)基本不支持桐早。
圖片壓縮
我們再來看一下一張圖片的加載過程:
圖片眾多以及圖片體積過大往往會影響頁面加載速度,造成不良的用戶體驗(yàn)燃异,有部分圖片達(dá)到幾百 kB腔呜,甚至 2M(這鍋必須運(yùn)營背瓢棒,非得上傳高清大圖不可?)陶衅,直接導(dǎo)致了加載時(shí)間過長。所以對于體積過大的圖片直晨,在保持圖片在可接受的清晰度范圍內(nèi)可適當(dāng)對圖片大小進(jìn)行壓縮搀军。
圖片壓縮又分為有損壓縮和無損壓縮。
有損壓縮
有損壓縮指在壓縮文件大小的過程中勇皇,損失了一部分圖片的信息罩句,也即降低了圖片的質(zhì)量(即圖片被壓糊了),并且這種損失是不可逆的敛摘。常見的有損壓縮手段是按照一定的算法將臨近的像素點(diǎn)進(jìn)行合并门烂。壓縮算法不會對圖片所有的數(shù)據(jù)進(jìn)行編碼壓縮,而是在壓縮的時(shí)候兄淫,去除了人眼無法識別的圖片細(xì)節(jié)屯远。因此有損壓縮可以在同等圖片質(zhì)量的情況下大幅降低圖片的體積。例如 jpg 格式的圖片使用的就是有損壓縮捕虽。
無損壓縮
無損壓縮指的是在壓縮圖片的過程中氓润,圖片的質(zhì)量沒有任何損耗。我們?nèi)魏螘r(shí)候都可以從無損壓縮過的圖片中恢復(fù)出原來的信息薯鳍。壓縮算法對圖片的所有的數(shù)據(jù)進(jìn)行編碼壓縮咖气,能在保證圖片的質(zhì)量的同時(shí)降低圖片的體積挨措。例如 png、gif 使用的就是無損壓縮崩溪。
下面是各種圖片格式的壓縮類型
image.png
工具壓縮
tinypng 免費(fèi)浅役、批量、速度塊
智圖壓縮? 百度很難搜到官網(wǎng)了伶唯,免費(fèi)觉既、批量、好用
squoosh? 在線圖片壓縮工具
compressor 支持 JPG乳幸、PNG瞪讼、SVG、GIF
webpack 壓縮
工程化的項(xiàng)目可以在 webpack 里面配置 image-webpack-loader 進(jìn)行圖片壓縮
1.安裝依賴
npm?install?--save-dev?image-webpack-loader
2.配置 webpack
使用 iconfont
iconfont(字體圖標(biāo))粹断,即通過字體的方式展示圖標(biāo)符欠,多用于渲染圖標(biāo)、簡單圖形瓶埋、特殊字體等希柿。
優(yōu)點(diǎn)
像使用字體一樣,設(shè)置大小养筒、顏色及其他樣式曾撤,不失真
輕量,易修改
有效減少 HTTP 請求次數(shù)
使用 base64 格式
原理:將圖片轉(zhuǎn)換為 base64 編碼字符串 inline 到頁面或 css 中晕粪。
優(yōu)點(diǎn)
提升性能: 網(wǎng)頁上的每一個(gè)圖片挤悉,都是需要消耗一個(gè) http 請求下載而來的, 圖片的下載始終都要向服務(wù)器發(fā)出請求,要是圖片的下載不用向服務(wù)器發(fā)出請求巫湘,base64 可以隨著 HTML 的下載同時(shí)下載到本地.減少 https 請求装悲。
加密: 讓用戶一眼看不出圖片內(nèi)容 , 只能看到編碼。
方便引用: 在多個(gè)文件同時(shí)使用某些圖片時(shí), 可以把圖片轉(zhuǎn)為 base64 格式的文件, 把樣式放在全局中, 比如 common.css, 以后在用的時(shí)候就可以直接加類名, 二不需要多層找文件路徑, 會提升效率
但需要注意的是:如果圖片較大剩膘,圖片的色彩層次比較豐富衅斩,則不適合使用這種方式,因?yàn)樵搱D片經(jīng)過 base64 編碼后的字符串非常大怠褐,會明顯增大 HTML 頁面的大小畏梆,從而影響加載速度。
base64 化最常見的就是在 url-loader 中使用奈懒。
module.exports?=?{
...
module:?{
rules:?[
{
test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader:'url-loader',
options:?{
limit:10240,
name:?utils.assetsPath('img/[name].[hash:7].[ext]'),
}
},
],
},
}
這樣就能將項(xiàng)目中小于 10kb 的圖片轉(zhuǎn)化為 base64 應(yīng)用到頁面中
使用 css 代替圖片奠涌。
比如實(shí)現(xiàn)修飾效果,如半透明磷杏、邊框溜畅、圓角、陰影极祸、漸變等慈格,在當(dāng)前主流瀏覽器中都可以用 CSS 達(dá)成怠晴,這樣能減少圖片的請求,達(dá)到優(yōu)化的目的浴捆。
缺點(diǎn)
受限于 css 的瀏覽器的兼容性
對于較復(fù)雜的圖案就無能為力了蒜田,寫也麻煩,開發(fā)成本大
使用 CDN 圖片
CDN 的全稱是 Content Delivery Network选泻,即內(nèi)容分發(fā)網(wǎng)絡(luò)冲粤。CDN 是構(gòu)建在網(wǎng)絡(luò)之上的內(nèi)容分發(fā)網(wǎng)絡(luò),依靠部署在各地的邊緣服務(wù)器页眯,通過中心平臺的負(fù)載均衡梯捕、內(nèi)容分發(fā)、調(diào)度等功能模塊窝撵,使用戶就近獲取所需內(nèi)容傀顾,降低網(wǎng)絡(luò)擁塞,提高用戶訪問響應(yīng)速度和命中率忿族。CDN 的關(guān)鍵技術(shù)主要有內(nèi)容存儲和分發(fā)技術(shù)锣笨。
舉個(gè)簡單的例子:
以前買火車票大家都只能去火車站買蝌矛,后來我們買火車票就可以在樓下的火車票代售點(diǎn)買了道批。
基本原理
CDN 的基本原理是廣泛采用各種緩存服務(wù)器,將這些緩存服務(wù)器分布到用戶訪問相對集中的地區(qū)或網(wǎng)絡(luò)中入撒,在用戶訪問網(wǎng)站時(shí)隆豹,利用全局負(fù)載技術(shù)將用戶的訪問指向距離最近的工作正常的緩存服務(wù)器上,由緩存服務(wù)器直接響應(yīng)用戶請求茅逮。
基本思路
CND 的基本思路是盡可能避開互聯(lián)網(wǎng)上有可能影響數(shù)據(jù)傳輸速度和穩(wěn)定性的瓶頸和環(huán)節(jié)璃赡,使內(nèi)容傳輸?shù)母臁⒏€(wěn)定献雅。通過在網(wǎng)絡(luò)各處放置節(jié)點(diǎn)服務(wù)器所構(gòu)成的在現(xiàn)有的互聯(lián)網(wǎng)基礎(chǔ)之上的一層智能虛擬網(wǎng)絡(luò)碉考,CDN 系統(tǒng)能夠?qū)崟r(shí)地根據(jù)網(wǎng)絡(luò)流量和各節(jié)點(diǎn)的連接、負(fù)載狀況以及到用戶的距離和響應(yīng)時(shí)間等綜合信息將用戶的請求重新導(dǎo)向離用戶最近的服務(wù)節(jié)點(diǎn)上挺身。其目的是使用戶可就近取得所需內(nèi)容侯谁,解決 Internet 網(wǎng)絡(luò)擁擠的狀況,提高用戶訪問網(wǎng)站的響應(yīng)速度章钾。
CDN 的優(yōu)勢
CDN 節(jié)點(diǎn)解決了跨運(yùn)營商和跨地域訪問的問題墙贱,訪問延時(shí)大大降低;
大部分請求在 CDN 邊緣節(jié)點(diǎn)完成贱傀,CDN 起到了分流作用惨撇,減輕了源站的負(fù)載。
圖片懶加載
懶加載是一種網(wǎng)頁性能優(yōu)化的方式府寒,它能極大的提升用戶體驗(yàn)魁衙。圖片一直是影響網(wǎng)頁性能的主要元兇报腔,現(xiàn)在一張圖片超過幾兆已經(jīng)是很經(jīng)常的事了。如果每次進(jìn)入頁面就請求所有的圖片資源剖淀,那么可能等圖片加載出來用戶也早就走了榄笙。所以進(jìn)入頁面的時(shí)候,只請求可視區(qū)域的圖片資源祷蝌。
總結(jié)出來就是:
減少資源的加載茅撞,頁面啟動(dòng)只加載首屏的圖片,這樣能明顯減少了服務(wù)器的壓力和流量巨朦,也能夠減小瀏覽器的負(fù)擔(dān)米丘。
防止并發(fā)加載的資源過多而阻塞 js 的加載,影響整個(gè)網(wǎng)站的啟動(dòng)糊啡,影響用戶體驗(yàn)
浪費(fèi)用戶的流量拄查,有些用戶并不想全部看完,全部加載會耗費(fèi)大量流量棚蓄。
原理
圖片懶加載的原理就是暫時(shí)不設(shè)置圖片的 src 屬性堕扶,而是將圖片的 url 隱藏起來,比如先寫在 data-src 里面梭依,等當(dāng)前圖片是否到了可視區(qū)域再將圖片真實(shí)的 url 放進(jìn) src 屬性里面稍算,從而實(shí)現(xiàn)圖片的延遲加載。
functionlazyload(){
letviewHeight?=document.body.clientHeight//獲取可視區(qū)高度
letimgs?=document.querySelectorAll('img[data-src]')
imgs.forEach((item,?index)?=>{
if(item.dataset.src?==='')return
//?用于獲得頁面中某個(gè)元素的左役拴,上糊探,右和下分別相對瀏覽器視窗的位置
letrect?=?item.getBoundingClientRect()
if(rect.bottom?>=0&&?rect.top?<?viewHeight)?{
item.src?=?item.dataset.src
item.removeAttribute('data-src')
}
})
}
//?可以使用節(jié)流優(yōu)化一下
window.addEventListener('scroll',?lazyload)
通過上面例子的實(shí)現(xiàn),我們要實(shí)現(xiàn)懶加載都需要去監(jiān)聽 scroll 事件河闰,盡管我們可以通過函數(shù)節(jié)流的方式來阻止高頻率的執(zhí)行函數(shù),但是我們還是需要去計(jì)算 scrollTop,offsetHeight 等屬性科平,有沒有簡單的不需要計(jì)算這些屬性的方式呢,答案是有的---IntersectionObserver
constimgs?=document.querySelectorAll('img[data-src]')
constconfig?=?{
rootMargin:'0px',
threshold:0,
}
letobserver?=newIntersectionObserver((entries,?self)?=>{
entries.forEach((entry)?=>{
if(entry.isIntersecting)?{
letimg?=?entry.target
letsrc?=?img.dataset.src
if(src)?{
img.src?=?src
img.removeAttribute('data-src')
}
//?解除觀察
self.unobserve(entry.target)
}
})
},?config)
imgs.forEach((image)?=>{
observer.observe(image)
})
圖片預(yù)加載
圖片預(yù)加載姜性,是指在一些需要展示大量圖片的網(wǎng)站瞪慧,將圖片提前加載到本地緩存中,從而提升用戶體驗(yàn)部念。
常用的方式有兩種弃酌,一種是隱藏在 css 的 background 的 url 屬性里面,一種是通過 javascript 的 Image 對象設(shè)置實(shí)例對象的 src 屬性實(shí)現(xiàn)圖片的預(yù)加載印机。
1矢腻、用 CSS 和 JavaScript 實(shí)現(xiàn)預(yù)加載
#preload-01{
background:url(http://domain.tld/image-01.png)?no-repeat?-9999px-9999px;
}
#preload-02{
background:url(http://domain.tld/image-02.png)?no-repeat?-9999px-9999px;
}
#preload-03{
background:url(http://domain.tld/image-03.png)?no-repeat?-9999px-9999px;
}
通過 CSS 的 background 屬性將圖片預(yù)加載到屏幕外的背景上。當(dāng)它們在 web 頁面的其他地方被調(diào)用時(shí)射赛,瀏覽器就會在渲染過程中使用預(yù)加載(緩存)的圖片多柑。該方法雖然高效,但仍有改進(jìn)余地楣责。使用該法加載的圖片會同頁面的其他內(nèi)容一起加載竣灌,增加了頁面的整體加載時(shí)間聂沙。
為了解決這個(gè)問題,我們增加了一些 JavaScript 代碼初嘹,來推遲預(yù)加載的時(shí)間及汉,直到頁面加載完畢。
functionpreloader(){
if(document.getElementById)?{
document.getElementById('preload-01').style.background?=
'url(http://domain.tld/image-01.png)?no-repeat?-9999px?-9999px'
document.getElementById('preload-02').style.background?=
'url(http://domain.tld/image-02.png)?no-repeat?-9999px?-9999px'
document.getElementById('preload-03').style.background?=
'url(http://domain.tld/image-03.png)?no-repeat?-9999px?-9999px'
}
}
functionaddLoadEvent(func){
varoldonload?=window.onload
if(typeofwindow.onload?!='function')?{
window.onload?=?func
}else{
window.onload?=function(){
if(oldonload)?{
oldonload()
}
func()
}
}
}
addLoadEvent(preloader)
2屯烦、使用 JavaScript 實(shí)現(xiàn)預(yù)加載
functionpreloader(){
if(document.images)?{
varimg1?=newImage()
varimg2?=newImage()
varimg3?=newImage()
img1.src?='http://domain.tld/path/to/image-001.gif'
img2.src?='http://domain.tld/path/to/image-002.gif'
img3.src?='http://domain.tld/path/to/image-003.gif'
}
}
functionaddLoadEvent(func){
varoldonload?=window.onload
if(typeofwindow.onload?!='function')?{
window.onload?=?func
}else{
window.onload?=function(){
if(oldonload)?{
oldonload()
}
func()
}
}
}
addLoadEvent(preloader)
響應(yīng)式圖片加載
什么是響應(yīng)式圖片加載坷随?其實(shí)就是在不同分辨率的設(shè)備上顯示不同尺寸的圖片,避免資源的浪費(fèi)驻龟。
常用的方法就是 css3 的媒體查詢(media query)温眉。
@mediascreenand(min-width:1200px)?{
img{
background-image:url('1.png');
}
}
@mediascreenand(min-width:992px)?{
img{
background-image:url('2.png');
}
}
@mediascreenand(min-width:768px)?{
img{
background-image:url('3.png');
}
}
@mediascreenand(min-width:480px)?{
img{
background-image:url('4.png');
}
}
此外,還可以使用 HTML5 的 picture 屬性進(jìn)行響應(yīng)式處理翁狐。方法如下:
創(chuàng)建 picture 標(biāo)簽类溢。
放置多個(gè) source 標(biāo)簽,以指定不同的圖像文件名露懒,進(jìn)而根據(jù)不同的條件進(jìn)行加載闯冷。
添加一個(gè)回退的元素
需要注意的是:現(xiàn)在很多瀏覽器對于 picture 這個(gè)標(biāo)簽還不支持,使用的時(shí)候需要加以注意懈词。
picture.png
漸進(jìn)式圖片
漸進(jìn)式圖片的意思是在高畫質(zhì)圖像加載完之前會先顯示低畫質(zhì)版本蛇耀。低畫質(zhì)版本由于畫質(zhì)低、壓縮率高钦睡,尺寸很小蒂窒,加載很快躁倒。在兩者之間我們也可以根據(jù)需要顯示不同畫質(zhì)的版本荞怒。
cat.png
漸進(jìn)式圖片可以讓用戶產(chǎn)生圖片加載變快的印象。用戶不再盯著一片空白區(qū)域等待圖片加載秧秉,而能看到圖像變得越來越清晰褐桌,這樣對用戶體驗(yàn)也是友好的。
骨架屏技術(shù)也是類似的原理象迎。
總結(jié)
選擇合適的圖片格式和壓縮大圖荧嵌,可從根源上截圖大圖加載過慢的問題。
使用雪碧圖砾淌,iconfont啦撮,base64,css 代替圖片等可減少圖片 http 請求汪厨,提高頁面加載速度赃春。
使用 CDN 圖片可達(dá)到分流的效果,減少服務(wù)券壓力劫乱。
圖片懶加載织中,預(yù)加載锥涕,漸進(jìn)式圖片等可不同程度減少白屏?xí)r間,提高產(chǎn)品體驗(yàn)狭吼。
---摘自微信公眾號“前端大全”