入手點(diǎn):
資源加載上
- 縮小首頁(yè)渲染時(shí)間:關(guān)鍵資源的數(shù)量和大小做限制
- 刪除不必要的代碼和注釋包括空格,盡量做到最小化文件
- 少用全局變量、緩存DOM節(jié)點(diǎn)查找的結(jié)果。減少IO讀取操作。打包的時(shí)候用 ModuleConcatenationPlugin 開啟 Scope Hoisting 作用域提升,提升代碼在瀏覽器中的執(zhí)行速度
- 利用瀏覽器的緩存機(jī)制
- 按需加載
DOM 操作頁(yè)面刷新次數(shù)上
- 減少http請(qǐng)求次數(shù)
- 用 innerHTML 代替 DOM 操作,減少 DOM 操作次數(shù),優(yōu)化 javascript 性能。
- 當(dāng)需要設(shè)置的樣式很多時(shí)設(shè)置 className 而不是直接操作 style。
- 事件委托,減少操作 DOM 的機(jī)會(huì)
圖片相關(guān)
優(yōu)化圖片著手點(diǎn):
- 減少像素點(diǎn)
- 減少每個(gè)像素點(diǎn)能夠顯示的顏色
具體方案:
- 修飾類圖片用 css 代替
- 用 CDN 加載圖片
- 小圖片轉(zhuǎn)位 base64 格式
- 雪碧圖:將多個(gè)圖標(biāo)文件整合到一張圖片中
- 選擇正確的圖片格式
照片使用 JPEG 格式
小圖片使用 PNG 格式,甚至是 SVG 格式
如果條件允許,可以用兼容性并不好的 WebP 格式,其具有更好的圖片壓縮算法因此體積更小而且具有肉眼識(shí)別無差異的圖片質(zhì)量
DNS(Domain Name System) 預(yù)解析
<link rel="dns-prefetch" >
DNS 的解析也是需要時(shí)間的,可以通過預(yù)解析預(yù)先獲得域名對(duì)應(yīng)的 IP 提高網(wǎng)頁(yè)的載入速度
節(jié)流 --- 控制頻率
所謂節(jié)流就是連續(xù)觸發(fā)事件,但是在 n 秒內(nèi)只執(zhí)行一次,節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率
場(chǎng)景:滾動(dòng)事件會(huì)發(fā)起網(wǎng)絡(luò)請(qǐng)求,但是我們不希望用戶在滾動(dòng)過程中一直發(fā)起請(qǐng)求,而是隔一段時(shí)間發(fā)起一次,這就需要節(jié)流
// fun 是用戶傳入需要防抖的函數(shù) wait 是等待時(shí)間
const throttle = ((fun, wait = 50) => {
// 上次函數(shù)執(zhí)行的時(shí)間
let lastTime = 0
return function(...args) {
// 當(dāng)前時(shí)間
let nowTime = + new Date()
// 將當(dāng)前時(shí)間和上一次函數(shù)執(zhí)行時(shí)間做對(duì)比,如果差值大于等待時(shí)間就執(zhí)行函數(shù)
if(nowTime - lastTime > wait) {
lastTime = nowTime
fun.apply(this, args)
}
}
})
setInterval(throttle(() => {
console.log('----------')
}, 500), 0)
防抖 --- 控制次數(shù)
所謂防抖就是事件在 n 秒內(nèi)只能執(zhí)行一次,如果在 n 秒內(nèi)又觸發(fā)了事件,則從新計(jì)算函數(shù)執(zhí)行時(shí)間
場(chǎng)景:有一個(gè)按鈕點(diǎn)擊觸發(fā)請(qǐng)求事件,但是我們不希望每次點(diǎn)擊都發(fā)起請(qǐng)求,而是用戶點(diǎn)擊一段時(shí)間之后沒有再次點(diǎn)擊的情況下發(fā)起請(qǐng)求,這種情況需要防抖
// fun 是用戶傳入需要防抖的函數(shù) wait 是等待時(shí)間
const debounce = ((fun, wait = 500) => {
// 緩存一個(gè)定時(shí)器 task
let task = null
// 這里定義的是用戶每次實(shí)際調(diào)用的防抖函數(shù)
// 如果已經(jīng)設(shè)置了定時(shí)器就清空上一次的定時(shí)器
// 開始一個(gè)新的定時(shí)器,延時(shí)執(zhí)行用戶傳入的方法
let taskFun = (() => {
if(task) clearTimeout(task)
task = setTimeout(() => {
fun()
}, wait)
})
taskFun()
})
let testFun = (() => {
return console.log('==========')
})
debounce(testFun, 2000)
預(yù)加載
針對(duì)一些不需要馬上用到,但是又希望盡早獲取的資源使用預(yù)加載
<link rel="preload" >
預(yù)加載是聲明式的 fetch 強(qiáng)制瀏覽器的加載但是不會(huì)阻塞 onload 事件
預(yù)加載可以降低首屏的加載時(shí)間,因?yàn)榭梢詫⒁恍┎挥绊懯灼恋侵匾奈募雍蠹虞d,缺點(diǎn)是兼容性不好
預(yù)渲染
可以將下載的文件預(yù)先在后臺(tái)進(jìn)行渲染
<link rel="prerender" >
可以提高頁(yè)面的渲染速度,但是要保證大概率被用戶點(diǎn)開,不然也是浪費(fèi)資源去渲染
懶執(zhí)行
將某些邏輯延遲到使用時(shí)再計(jì)算。該技術(shù)可以用于首屏優(yōu)化,對(duì)于某些耗時(shí)邏輯并不需要在首屏就使用的,就可以使用懶執(zhí)行。懶執(zhí)行需要喚醒,一般可以通過定時(shí)器或者事件的調(diào)用來喚醒。
懶加載
將不關(guān)鍵的資源延后加載:圖片懶加載,表格懶加載
CDN
原理:盡可能的在各個(gè)地方分布機(jī)房緩存數(shù)據(jù),這樣即使我們的根服務(wù)器遠(yuǎn)在國(guó)外,在國(guó)內(nèi)的用戶也可以通過國(guó)內(nèi)的機(jī)房迅速加載資源。
我們可以將靜態(tài)資源盡量使用 CDN 加載,由于瀏覽器對(duì)于單個(gè)域名有并發(fā)請(qǐng)求上限,可以考慮使用多個(gè) CDN 域名。并且對(duì)于 CDN 加載靜態(tài)資源需要注意 CDN 域名要與主站不同,否則每次請(qǐng)求都會(huì)帶上主站的 Cookie,平白消耗流量。