Ⅰ 前端性能優化總結(一)-js、css優化
移動互聯網時代,用戶對於網頁的打開速度要求越來越高。首屏作為直面用戶的第一屏,其重要性不言而喻。優化用戶體驗更是我們前端開發非常需要 focus 的東西之一。
從用戶的角度而言,當打開一個網頁,往往關心的是從輸入完網頁地址後到最後展現完整頁面這個過程需要的時間,這個時間越短,用戶體驗越好。所以作為網頁的開發者,就從輸入url到頁面渲染呈現這個過程中去提升網頁的性能。
所以輸入URL後發生了什麼呢?在瀏覽器中輸入url會經歷域名解析、建立TCP連接、發送http請求、資源解析等步驟。
http緩存優化是網頁性能優化的重要一環,這一部分我會在後續筆記中做一個詳細總結,所以本文暫不多做詳細整理。本文主要從網頁渲染過程、網頁交互以及Vue應用優化三個角度對性能優化做一個小結。
首先談談拿到服務端資源後瀏覽器渲染的流程:
關鍵渲染路徑是瀏覽器將 HTML、CSS、JavaScript 轉換為在屏幕上呈現的像素內容所經歷的一系列步驟。也就是我們剛剛提到的的的瀏覽器渲染流程。
為盡快完成首次渲染,我們需要最大限度減小以下三種可變因素:
首先,DOM 和 CSSOM 通常是並行構建的,所以 CSS 載入不會阻塞 DOM 的解析。
然而,由於 Render Tree 是依賴於 DOM Tree 和 CSSOM Tree 的,
所以他必須等待到 CSSOM Tree 構建完成,也就是 CSS 資源載入完成(或者 CSS 資源載入失敗)後,才能開始渲染。因此,CSS 載入會阻塞 Dom 的渲染。
由此可見,對於 CSSOM 縮小、壓縮以及緩存同樣重要,我們可以從這方面考慮去優化。
當瀏覽器遇到 script 標記時,會阻止解析器繼續操作,直到 CSSOM 構建完畢,JavaScript 才會運行並繼續完成 DOM 構建過程。
當頁面中元素樣式的改變並不影響它在文檔流中的位置時(例如:color、background-color、visibility 等),瀏覽器會將新樣式賦予給元素並重新繪制它,這個過程稱為重繪。
迴流(Reflow)
當 Render Tree 中部分或全部元素的尺寸、結構、或某些屬性發生改變時,瀏覽器重新渲染部分或全部文檔的過程稱為迴流。
有時即使僅僅迴流一個單一的元素,它的父元素以及任何跟隨它的元素也會產生迴流。現代瀏覽器會對頻繁的迴流或重繪操作進行優化:瀏覽器會維護一個隊列,把所有引起迴流和重繪的操作放入隊列中,如果隊列中的任務數量或者時間間隔達到一個閾值的,瀏覽器就會將隊列清空,進行一次批處理,這樣可以把多次迴流和重繪變成一次。
當你訪問以下屬性或方法時,瀏覽器會立刻清空隊列:
因為隊列中可能會有影響到這些屬性或方法返回值的操作,即使你希望獲取的信息與隊列中操作引發的改變無關,瀏覽器也會強行清空隊列,確保你拿到的值是最精確的。
避免頻繁操作樣式,最好一次性重寫 style 屬性,或者將樣式列表定義為 class 並一次性更改 class 屬性。
避免頻繁操作 DOM,創建一個 documentFragment,在它上面應用所有 DOM 操作,最後再把它添加到文檔中。
也可以先為元素設置 display: none,操作結束後再把它顯示出來。因為在 display 屬性為 none 的元素上進行的 DOM 操作不會引發迴流和重繪。
避免頻繁讀取會引發迴流/重繪的屬性,如果確實需要多次使用,就用一個變數緩存起來。
對具有復雜動畫的元素使用絕對定位,使它脫離文檔流,否則會引起父元素及後續元素頻繁迴流。
圖片懶載入在一些圖片密集型的網站中運用比較多,通過圖片懶載入可以讓一些不可視的圖片不去載入,避免一次性載入過多的圖片導致請求阻塞(瀏覽器一般對同一域名下的並發請求的連接數有限制),這樣就可以提高網站的載入速度,提高用戶體驗。
將頁面中的img標簽src指向一張小圖片或者src為空,然後定義data-src(這個屬性可以自定義命名,我才用data-src)屬性指向真實的圖片。src指向一張默認的圖片,否則當src為空時也會向伺服器發送一次請求。可以指向loading的地址。注意,圖片要指定寬高。
當載入頁面時,先把可視區域內的img標簽的data-src屬性值負給src,然後監聽滾動事件,把用戶即將看到的圖片載入。這樣便實現了懶載入。
事件委託其實就是利用JS事件冒泡機制把原本需要綁定在子元素的響應事件(click、keydown……)委託給父元素,讓父元素擔當事件監聽的職務。事件代理的原理是DOM元素的事件冒泡。
優點:
例如有一個列表需要綁定點擊事件,每一個列表項的點擊都需要返回不同的結果。
傳統寫法:
傳統方法會利用for循環遍歷列表為每一個列表元素綁定點擊事件,當列表中元素數量非常龐大時,需要綁定大量的點擊事件,這種方式就會產生性能問題。這種情況下利用事件委託就能很好的解決這個問題。
改用事件委託:
輸入搜索時,可以用防抖debounce等優化方式,減少http請求;
這里以滾動條事件舉例:防抖函數 onscroll 結束時觸發一次,延遲執行
節流函數:只允許一個函數在N秒內執行一次。滾動條調用介面時,可以用節流throttle等優化方式,減少http請求;
下面還是一個簡單的滾動條事件節流函數:節流函數 onscroll 時,每隔一段時間觸發一次,像水滴一樣
參考鏈接: https://zhuanlan.hu.com/p/113864878?from_voters_page=true
Ⅱ 前端性能優化的具體方法有哪些
解決辦法一:
減少http請求次數:CSS Sprites, JS、CSS源碼壓縮、圖片大小控制合適;網頁Gzip,CDN託管,data緩存 ,圖片伺服器。
前端模板 JS+數據,減少由於HTML標簽導致的帶寬浪費,前端用變數保存AJAX請求結果,每次操作本地變數,不用請求,減少請求次數
用innerHTML代替DOM操作,減少DOM操作次數,優化javascript性能。
當需要設置的樣式很多時設置className而不是直接操作style。
少用全局變數、緩存DOM節點查找的結果。減少IO讀取操作。
避免使用CSS Expression(css表達式)又稱Dynamic properties(動態屬性)。
圖片預載入,將樣式表放在頂部,將腳本放在底部 加上時間戳。
解決辦法二:
減少HTTP請求次數
使用CDN:CDN在前端開發的作用
避免空的src和href
為文件頭指定Expires
使用gzip壓縮內容
把CSS放到頂部
把JS放到底部
避 免使用CSS表達式
將CSS和JS放到外部文件中
避免跳轉
可緩存的AJAX
使用GET來完成AJAX請求
Ⅲ 前端網站常規優化方案
1、減少請求次數
2、減小資源大小
3、提高響應和載入速度
4、優化資源載入時機
5、優化載入方式
1、合並、壓縮、混淆html/css/js文件(webpack實現,減小資源大小)
2、Nginx開啟Gzip,進一步壓縮資源(減小資源大小)
3、圖片資源使用CDN加速(提高載入速度)
4、符合條件的圖標做base64處理(減小資源大小)
5、樣式表放首部,JS放尾部(JS單線程,會阻塞頁面;資源載入方式)
6、設置緩存(強緩存和協商緩存,提高載入速度)
7、link或者src添加rel屬性,設置prefetch或preload可預載入資源。(載入時機)
8、如果使用了UI組件庫,採用按需載入(減小資源大小)
9、SPA項目,通過import或者require做路由按需(減小資源大小)載入
10、服務端渲染SSR,加快首屏渲染,利於SEO
11、頁面使用骨架屏,提高首頁載入速度(提高載入速度)
12、使用 JPEG 2000, JPEG XR, and WebP 的圖片格式來代替現有的jpeg和png,當頁面圖片較多時,這點作用非常明顯
13、使用圖片懶載入-lazyload
Ⅳ 提高Web前端性能的技巧有哪些
今天小編要跟大家分享的文章是關於提高web前端性能的技巧有哪些?當今數字世界,存在著無數的網站,每天都需要處理各種不同的原因的訪問。然而,這些網站中有很大一部分顯得笨重,使用起來也很麻煩。沒怎麼優化的網站會被各種各樣的問題困擾,包括載入時間、不支持移動設備、瀏覽器兼容性問題,等等。
這篇文章講述可以幫助改善優化前端的技術,非常有用。主要內容有清理代碼、壓縮圖片、壓縮外部資源、使用CDN,以及一些其它方法。這些方法會為你的網站帶顯著的速度提升和整體性能提升。下面來和小編一起看一看吧!
1.清理HTML文檔
HTML,即超文本標記語言,幾乎是所有網站的支柱。HTML為網頁帶來標題、子標題、列表和其它一些文檔結構的格式。在最近更新的HTML5中,甚至可以創建圖表。
HTML很容易被網路爬蟲識別,因此搜索引擎可以根據網站的內容在一定程度上實時更新。在寫HTML的時候,你應該嘗試讓它簡潔而有效。此外,在HTML文檔中引用外部資源的時候也需要遵循一些最佳實踐方法。
恰當放置CSS
Web設計者喜歡在網頁建立起主要的HTML骨架之後再來創建樣式表。這樣一來,網頁中的樣式表往往會放在HTML的後面,接近文檔結束的地方。然而推薦的做法是把CSS放在HTML的上面部分,文檔頭之內,這可以確保正常的渲染過程。
_飧霾唄圓荒芴岣咄鏡募釉廝俁齲換崛梅夢收叱な奔淇醋趴瞻灼聊換蛘呶薷袷降奈謀荊_OUT)等待。如果網頁大部分可見元素已經載入出來了,訪問者才更有可能等待載入整個頁面,從而帶來對前端的優化效果。這就是知覺性能。
正確放置Javascript
另一方面,如果將JavaScript放置在head標簽內或HTML文檔的上部,這會阻塞HTML和CSS元素的載入過程。這個錯誤會導致頁面載入時間增長,增加用戶等待時間,容易讓人感到不耐煩而放棄對網站的訪問。不過,您可以通過將JavaScript屬性置於_TML底部來避免此問題。
此外,在使用JavaScript時,人們通常喜歡用非同步腳本載入。這會阻止
//鏈式調用時文件逐個下載,.wait()用來指定文件下載並執行完畢後所調用的函數
$LAB.script('./a.js')_
.script('./b.js')_
.wait(function(){__
_pp.init();
})
//為了保證執行順序,可以這么做,此時a必定在b前執行
$LAB.script('./a.js').wait()_
.script('./b.js')_
.wait(function(){___
_pp.init();
})
二.數據存取與JS性能
1.在js中,數據存儲的位置會對代碼整體性能產生重大影響。數據存儲共有4種方式:字面量,變數,數組項,對象成員。他們有著各自的性能特點。
2.訪問字面量和局部變數的速度最快,相反,訪問數組和對象相對較慢
3.由於局部變數存在於作用域鏈的起始位置,因此訪問局部變數的比訪問跨域作用變數更快
4.嵌套的對象成員會明顯影響性能,應盡量避免
5.屬性和方法在原型鏈位置越深,訪問他的速度越慢
6.通常我們可以把需要多次使用的對象成員,數組元素,跨域變數保存在局部變數中來改善js性能
三.DOM編程
1.訪問DOM會影響瀏覽器性能,修改DOM則更耗費性能,因為他會導致瀏覽器重新計算頁面的幾何變化。<通常的做法是減少訪問DOM的次數,把運算盡量留在JS這一端。
註:如過在一個對性能要求比較高的操作中更新一段HTML,推薦使用innerHTML,因為它在絕大多數瀏覽器中運行的都很快。但對於大多數日常操作而言,並沒有太大區別,所以你更應該根據可讀性,穩定性,團隊習慣,代碼風格來綜合決定使用innerHTML還是createElement()
2.HTML集合優化
HTML集合包含了DOM節點引用的類數組對象,一直與文檔保持連接,每次你需要最新的信息時,都會重復執行查詢操作,哪怕只是獲取集合里元素的個數。
①_優化一——集合轉數組collToArr
functioncollToArr(coll){_
for(vari=0,a=[],len=coll.length;i
a._ush(coll[i]);
__
returna
}
②緩存集合length
③訪問集合元素時使用局部變數(即將重復的集合訪問緩存到局部變數中,用局部變數來操作)
3.遍歷DOM
①使用只返回元素節點的API遍歷DOM,因為這些API的執行效率比自己實現的效率更高:
td{border:1pxsolid#ccc;padding:5px;margin:auto;}
td>p{text-align:left;}
td>pspan{text-align:center;display:block;}
屬性名
被替代屬性
children
childNodes
childElementCount
childNodes.length
firstElementChild
firstChild
lastElementChild
lastChild
nextElementSibling
nextSibling
previousElementSibling
previousSibling
_諮≡衿_PI——querySelectorAll()
querySelectorAll()方法使用css選擇器作為參數並返回一個NodeList——包含著匹配節點的類數組對象,該方法不會返回HTML集合,因此返回的節點不會對應實時文檔結構,著也避免了HTML集合引起的性能問題。
let_rr=_ocument.querySelectorAll('div.warning,_iv.notice>_')
4.重繪和重排
瀏覽器在下載完頁面的所有組件——html,js,css,圖片等之後,會解析並生成兩個內部數據結構——_OM樹,渲染樹.一旦DOM樹和渲染樹構建完成,瀏覽器就開始繪制頁面元素(paint).
①重排發生的條件:
添加或刪除可見的DOM元素位置變化元素尺寸改變內容改變頁面渲染器初始化瀏覽器窗口尺寸變化出現滾動條時會觸發整個頁面的重排_嘏瘧囟ㄖ鞀
5.渲染樹變化的排列和刷新
大多數瀏覽器通過隊列化修改並批量執行來優化重排過程,然而獲取布局信息的操作會導致隊列強制刷新。
offsetTop,offsetWidth...
scrollTop,scrollHeight...
clientTop,clientHeight...
getComputedStyle()
一些優化建議:將設置樣式的操作和獲取樣式的操作分開:
//設置樣式
body.style.color='red'
body.style.fontSize=པpx'
//讀取樣式
letcolor=body.style.color
let_ontSize=_ody.style.fontSize
另外,獲取計算屬性的兼容寫法:
functiongetComputedStyle(el){_
varcomputed=(document.body.currentStyle?el.currentStyle:document.defaultView.getComputedStyle(el,'');_
returncomputed
}
6.最小化重繪和重排
①.批量改變樣式
/*使用cssText
*/el.style.cssText='border-left:1px;_order-right:2px;_adding:20px'
②.批量修改dom的優化方案——使元素脫離文檔流-對其應用多重改變-把元素帶迴文檔
functionappendDataToEl(option){
vartargetEl=option.target||document.body,___
createEl,___
data=option.data||[];_//讓容器脫離文檔流,減少重繪重排_
vartargetEl_display=targetEl.style.display;_
targetEl.style.display='none'
_
//*****創建文檔片段來優化Dom操作****_
varfragment=document.createDocumentFragment();_//給元素填充數據_
for(vari=0,max=data.length;i
createEl=
document.createElement(option.createEl);___
for(varitemindata[i]){_____
if(item.toString()==='text'){_______
createEl.appendChild(document.createTextNode(data[i][item]));________ontinue;___________
_f(item.toString()==='html'){_______
createEl.innerHTML=item,data[i][item];_______
continue;_____
}_____
_reateEl.setAttribute(item,data[i][item]);_______
//****將填充好的node插入文檔片段****___
fragment.appendChild(createEl);___
//****將文檔片段統一插入目標容器****_
targetEl.appendChild(fragment);_
//顯示容器,完成數據填充_
targetEl.style.display=
targetEl_display;
}
//使用
varwrap=document.querySelectorAll('.wrap')[0];
vardata=[_
_name:'xujaing',text:'選景',title:'xuanfij'},_
{name:'xujaing',text:'選景',title:'xuanfij'},_
{name:'xujaing',text:'選景',title:'xuanfij'}];
appendDataToEl({_
target:wrap,_
createEl:'div',
_ata:data
});
上面的優化方法使用了文檔片段:_蔽頤前鹽牡燈尾迦氳澆詰闃惺保導噬媳惶砑擁鬧皇歉悶蔚淖詠詰悖皇瞧偽舊懟?梢允溝_om操作更有效率。
②.緩存布局信息
//緩存布局信息
letcurrent=el.offsetLeft;
current++;
el.style.left=current+'px'
if(current>300){_
stop();
}
④.慎用:hover
如果有大量元素使用:hover,那麼會降低相應速度,CPU升高
⑤.使用事件委託(通過事件冒泡實現)來減少事件處理器的數量,減少內存和處理時間
functiondelegation(e,selector,callback){_
e=e||window.event;_
vartarget=e.target||e.srcElement;
_if(target.nodeName!==selector||
target.className!==selector||target.id!==selector){___
return;
_}_
if(typeofe.preventDefault==='function'){__
_.preventDefault();___
e.stopPropagation();
}else{___
e.returnValue=false;
e.cancelBubble=true;_
}
__allback()}
四.演算法和流程式控制制
1.循環中減少屬性查找並反轉(可以提升50%-60%的性能)
//for循環
for(vari=item.length;i--){_
process(item[i]);
}
//while循環
varj=item.length;
while(j--){_
process(item[i]);
}
2.使用Duff裝置來優化循環(該方法在後面的文章中會詳細介紹)
3.基於函數的迭代(比基於循環的迭代慢)
items.forEach(function(value,index,array){__rocess(value);})
4.通常情況下switch總比if-else快,但是不是最佳方案
五.字元串和正則表達式
1.除了IE外,其他瀏覽器會嘗試為表達式左側的字元串分配更多的內存,然後簡單的將第二個字元串拷貝到他的末尾,如果在一個循環中,基礎字元串位於最左側,就可以避免重復拷貝一個逐漸變大的基礎字元串。2.使用[sS]來匹配任意字元串3.去除尾部空白的常用做法:
if(!String.prototype.trim){_
String.prototype.trim=function(){___
returnthis.replace(/^s+/,'').replace(/ss*$/,'')_
}
}
六.快速響應的用戶界面
1.瀏覽器的UI線程:用於執行javascript和更新用戶界面的進程。
2.在windows系統中定時器解析度為15毫秒,因此設置小於15毫秒將會使IE鎖定,延時的最小值建議為25ms.
3.用延時數組分割耗時任務:
functionmultistep(steps,args,callback){_
vartasks=steps.concat();
__etTimeout(function(){___
vartask=tasks.shift();___
task.apply(null,args||[]);_//調用Apply參數必須是數組
___
if(tasks.length>0){_____
setTimeout(arguments.callee,25);
___else{_____
_allback();___
__
},25);
}
4.記錄代碼運行時間批處理任務:
functiontimeProcessArray(items,process,callback){_
vartodo=item.concat();__etTimeout(function(){___
varstart=+newDate();
__o{_____
_rocess(todo.shift());___
}while(todo.length>0&&(+newDate()-start<50));
____f(todo.length>0){_____
_etTimeout(arguments.callee,25);
___else{____
_allback(items);_
}_
_,25)
}
5.使用WebWorker:它引入了一個介面,能使代碼運行且不佔用瀏覽器UI線程的時間。一個Worker由如下部分組成:
①一個navigator對象,包括app
Ⅶ 常用的前端性能優化方法有哪些
1、減少http請求,合理設置HTTP緩存
2、使用瀏覽器緩存
3、啟用壓縮
4、CSS Sprites,合並 CSS圖片,減少請求數
5、CSS放在頁面最上部,javascript放在頁面最下面