前端性能優(yōu)化--圖片
圖片格式的選擇
JPEG
有損壓縮,高品質(zhì)的壓縮方式。圖片體積壓縮至原有體積的50%以下時(shí)糯崎,jpg仍然可以保持60%的品質(zhì)几缭。原理為以24位存儲(chǔ)單個(gè)圖,可以呈現(xiàn)多達(dá)1600萬(wàn)種顏色沃呢,足以滿足大多數(shù)場(chǎng)景下對(duì)色彩的要求年栓,這一點(diǎn)決定了它壓縮前后的質(zhì)量損耗并不容易被肉眼察覺(jué)。
優(yōu)點(diǎn):
網(wǎng)站呈現(xiàn)豐富的色彩薄霜。
有損壓縮某抓,通過(guò)壓縮大大的減少圖片的體積。一般圖片用60%級(jí)別比較合適惰瓜,大于75%的壓縮等級(jí)否副,圖片有明顯的質(zhì)量下降。
無(wú)兼容性問(wèn)題崎坊。
缺點(diǎn):
JPEG圖像不支持透明度的處理备禀,透明圖片使用PNG。
處理矢量圖形和logo等線條感較強(qiáng)奈揍、顏色對(duì)比強(qiáng)烈的圖像時(shí)曲尸,人為壓縮的圖片模糊會(huì)相當(dāng)明顯。
使用場(chǎng)景:
- 適用于色彩豐富的圖片男翰,日常開(kāi)發(fā)中另患,JPEG圖片經(jīng)常作為大的背景圖、輪播圖或banner圖出現(xiàn)蛾绎。
PNG
無(wú)損壓縮昆箕,高保真的圖片格式。同時(shí)支持8位和24位二進(jìn)制的位數(shù)租冠,八位的png最多指出256種顏色为严,24位可以呈現(xiàn)約1600萬(wàn)種。
優(yōu)點(diǎn):
網(wǎng)站呈現(xiàn)豐富的色彩肺稀,更強(qiáng)的色彩表現(xiàn)力第股,對(duì)線條的處理更加細(xì)膩。
支持透明度處理话原,透明圖片的使用夕吻。
缺點(diǎn):
- 體積太大
使用場(chǎng)景:
線條和對(duì)比度處理更具優(yōu)勢(shì)诲锹,我們主要用它來(lái)呈現(xiàn)小的logo、顏色簡(jiǎn)單且對(duì)比強(qiáng)烈的圖片或?qū)Ρ鹊取?/p>
添加透明度涉馅,使用透明圖片归园。
GIF
最多支持256種顏色的8位無(wú)損圖片格式。
優(yōu)點(diǎn):
支持256種顏色稚矿,文件體積小庸诱。
支持透明。
支持動(dòng)畫(huà)晤揣。
缺點(diǎn):
- 只支持簡(jiǎn)單色彩的圖片桥爽。
使用場(chǎng)景:
展示無(wú)限循環(huán)的動(dòng)畫(huà),比如圖標(biāo)昧识、表情钠四、廣告位等。
簡(jiǎn)單色彩的圖片使用跪楞。
webP
同時(shí)提供了有損壓縮和無(wú)損壓縮(可逆壓縮)的圖片文件格式缀去。像JPEG一樣對(duì)細(xì)接豐富的圖片信手拈來(lái),像PNG一樣支持透明甸祭,像GIF一樣可以顯示動(dòng)態(tài)圖片缕碎。
優(yōu)點(diǎn):
色彩豐富。
支持透明池户。
支持動(dòng)態(tài)圖片阎曹。
無(wú)損壓縮比PNG壓縮減少了45%的文件大小。
缺點(diǎn):
- 瀏覽器對(duì)webP支持并不普遍煞檩。ios系統(tǒng)基本不支持处嫌。
圖片壓縮
有損壓縮
在壓縮文件大小的過(guò)程中,損失了一部分圖片的信息斟湃,也降低了圖片的質(zhì)量熏迹,并且這種損失是不可逆的。常見(jiàn)的壓縮手段是按照一定的算法將鄰近的像素點(diǎn)進(jìn)行合并凝赛,去除了人肉眼無(wú)法識(shí)別的圖片細(xì)節(jié)注暗。jpg圖片使用的就是有損壓縮。
無(wú)損壓縮
在壓縮的過(guò)程中墓猎,圖片的質(zhì)量沒(méi)有任何損傷捆昏。任何時(shí)候都可以從無(wú)損壓縮過(guò)的圖片中恢復(fù)出原來(lái)的信息。壓縮算法是對(duì)圖片的所有的數(shù)據(jù)進(jìn)行編碼壓縮毙沾,能在保證圖片的質(zhì)量的同時(shí)降低圖片的體積骗卜。例如png、gif使用的就是無(wú)損壓縮。
類型 | 動(dòng)畫(huà) | 壓縮類型 | 瀏覽器支持 | 透明度 |
---|---|---|---|---|
GIF | 支持 | 無(wú)損 | 所有 | 支持 |
PNG | 不支持 | 無(wú)損 | 所以 | 支持 |
JPEG | 不支持 | 有損 | 所以 | 不支持 |
webP | 支持 | 無(wú)損或有損 | 部分支持 | 支持 |
壓縮工具
webpack 壓縮
webpack配置imge-webpack-loader進(jìn)行圖片壓縮
1.安裝依賴
npm install --save-dev image-webpack-loader
2.配置webpack
module.exports = {
...
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[hash:7].[ext]'
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 50,
},
optipng: {
enabled: true,
},
pngquant: {
quality: [0.5, 0.65],
speed: 4,
},
gifsicle: {
interlaced: false,
}
},
},
],
},
],
},
}
使用雪碧圖
雪碧圖寇仓,CSS Sprites举户,國(guó)內(nèi)也叫 CSS 精靈,是一種 CSS 圖像合成技術(shù)遍烦,主要用于小圖片顯示俭嘁。
瀏覽器請(qǐng)求資源的時(shí)候,同源域名請(qǐng)求資源的時(shí)候有最大并發(fā)限制服猪,chrome 為 6 個(gè)供填,就比如你的頁(yè)面上有 10 個(gè)相同 CDN 域名小圖片,那么需要發(fā)起 10 次請(qǐng)求去拉取罢猪,分兩次并發(fā)近她。第一次并發(fā)請(qǐng)求回來(lái)后,發(fā)起第二次并發(fā)坡脐。如果你把 10 個(gè)小圖片合并為一張大圖片的畫(huà),那么只用一次請(qǐng)求即可拉取下來(lái) 10 個(gè)小圖片的資源房揭。減少服務(wù)器壓力备闲,減少并發(fā),減少請(qǐng)求次數(shù)捅暴。
優(yōu)點(diǎn):
- 減少請(qǐng)求個(gè)數(shù)恬砂。
缺點(diǎn):
- 生成圖片體積大,減少請(qǐng)求個(gè)數(shù)同時(shí)增加了圖片大小蓬痒。
webpack合成雪碧圖
有相應(yīng)的插件提供了自動(dòng)合成雪碧圖的功能并且可以自動(dòng)生成對(duì)應(yīng)的樣式文件webpack-spritesmith
var path = require('path')
var SpritesmithPlugin = require('webpack-spritesmith')
module.exports = {
// ...
plugins: [
new SpritesmithPlugin({
src: {
cwd: path.resolve(__dirname, 'src/ico'),
glob: '*.png',
},
target: {
image: path.resolve(__dirname, 'src/spritesmith-generated/sprite.png'),
css: path.resolve(__dirname, 'src/spritesmith-generated/sprite.styl'),
},
apiOptions: {
cssImageRef: '~sprite.png',
},
}),
],
}
將src/ico目錄下的所有png文件合成雪碧圖泻骤,并且輸出到對(duì)應(yīng)目錄,同時(shí)還可以生成對(duì)應(yīng)的樣式文件梧奢,樣式文件的語(yǔ)法會(huì)根據(jù)你配置的樣式文件的后綴動(dòng)態(tài)生成狱掂。
使用base64格式
將圖片轉(zhuǎn)換為base64編碼字符串inline到頁(yè)面或css中。
優(yōu)點(diǎn):
性能提升:減少http請(qǐng)求亲轨,base64可以隨著HTML下載到本地趋惨。
加密:用戶無(wú)法一眼看到圖片的內(nèi)容,只看到編碼惦蚊。
方便引用:全局公共文件內(nèi)加類名器虾。
缺點(diǎn):
- 圖片大,圖片色彩層次比較豐富蹦锋,不適合這種方式兆沙,base64編碼后文件過(guò)大,增加HTML頁(yè)面的大小莉掂,影響加載速度葛圃。
webpack配置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]'),
}
},
],
},
}
圖片懶加載
圖片懶加載的原理就是暫時(shí)不設(shè)置圖片的 src 屬性,而是將圖片的 url 隱藏起來(lái),比如先寫(xiě)在 data-src 里面装悲,等當(dāng)前圖片是否到了可視區(qū)域再將圖片真實(shí)的 url 放進(jìn) src 屬性里面昏鹃,從而實(shí)現(xiàn)圖片的延遲加載。
優(yōu)點(diǎn):
減少資源的加載诀诊,頁(yè)面啟動(dòng)只加載首屏的圖片洞渤,這樣能明顯減少服務(wù)器的壓力和流量,也能減小瀏覽器的負(fù)擔(dān)属瓣。
防止并發(fā)加載的資源過(guò)多而阻塞js的加載载迄,影響整個(gè)網(wǎng)站的啟動(dòng),影響用戶體驗(yàn)抡蛙。
節(jié)省用戶流量护昧,有些用戶并不想全部看完,全部加載會(huì)耗費(fèi)大量流量粗截。
js代碼
function lazyload() {
let viewHeight = document.body.clientHeight //獲取可視區(qū)高度
let imgs = document.querySelectorAll('img[data-src]')
imgs.forEach((item, index) => {
if (item.dataset.src === '') return
// 用于獲得頁(yè)面中某個(gè)元素的左惋耙,上,右和下分別相對(duì)瀏覽器視窗的位置
let rect = 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)
IntersectionObserver計(jì)算位置
const imgs = document.querySelectorAll('img[data-src]')
const config = {
rootMargin: '0px',
threshold: 0,
}
let observer = new IntersectionObserver((entries, self) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let img = entry.target
let src = 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àn)绽榛。
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;
}
function preloader() {
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'
}
}
function addLoadEvent(func) {
var oldonload = window.onload
if (typeof window.onload != 'function') {
window.onload = func
} else {
window.onload = function () {
if (oldonload) {
oldonload()
}
func()
}
}
}
addLoadEvent(preloader)
2.使用JavaScript實(shí)現(xiàn)預(yù)加載
function preloader() {
if (document.images) {
var img1 = new Image()
var img2 = new Image()
var img3 = new Image()
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'
}
}
function addLoadEvent(func) {
var oldonload = window.onload
if (typeof window.onload != 'function') {
window.onload = func
} else {
window.onload = function () {
if (oldonload) {
oldonload()
}
func()
}
}
}
addLoadEvent(preloader)
漸進(jìn)式圖片
高品質(zhì)圖像加載完之前會(huì)先顯示低畫(huà)質(zhì)版本。低畫(huà)質(zhì)版本由于畫(huà)質(zhì)低婿屹、壓縮率高灭美、尺寸小、加載很快昂利。
普通圖片渲染時(shí)届腐,數(shù)據(jù)將按照存儲(chǔ)時(shí)的順序從上到下逐行掃描被顯示出來(lái)的,直到所有的數(shù)據(jù)都被讀取完畢蜂奸,就完成了整張圖片的顯示犁苏。
漸進(jìn)式圖片渲染過(guò)程中,會(huì)先顯示整個(gè)圖片的模糊輪廓扩所,隨著掃描次數(shù)的增加傀顾,圖片變得越來(lái)越清晰。這種格式的主要優(yōu)點(diǎn)是在網(wǎng)絡(luò)較慢的情況下碌奉,可以看到圖片的輪廓知道正在加載的圖片大概是什么短曾。
注:
很多工具和庫(kù)都支持導(dǎo)出漸進(jìn)式JPEG,比如 ImageMagick, libjpeg, jpegtran, jpeg-recompress以及imagemin赐劣。 也可以使用 gulp-imagemin 進(jìn)行批量轉(zhuǎn)換嫉拐。
Photoshop導(dǎo)出漸進(jìn)式圖片,保存為JPEG格式魁兼,勾選連續(xù)婉徘。