前端優化(原創)

前端優化只要在兩方面進行,一是加載速度優化,二是渲染速度優化。在進行優化前,先掌握好2個基本理論知識css

 

理論知識(一):瀏覽器的完整加載渲染過程html

①輸入url,發送請求
②加載(即下載)整個.html文件
③加載完後解析(即運行)html,並在解析的過程當中構建DOM樹
·JavaScript是單線程的。瀏覽器是多線程的:有的線程負責加載資源,有的線程負責執行腳本,有的線程負責渲染界面。
·瀏覽器按從上之下(深度遍歷)的原則解析各個html標籤
·解析標籤的過程就是構建DOM樹的過程
·解析遇到link、script、img標籤時,瀏覽器會向服務器發送請求資源。
script加載時不影響其餘資源加載,但因爲不知道js中的執行內容,因此須要等JS加載並執行完後纔會繼續解析和渲染。
script的執行會阻塞html解析、其餘下載線程以及渲染線程。
link加載完css後會解析爲CSSOM(層疊樣式表對象模型,一棵僅含有樣式信息的樹)。css的加載和解析不會阻塞html的解析,但會阻塞渲染。
img的加載不會阻塞html的解析,但img加載後並不渲染,它須要等待Render Tree生成完後才和Render Tree一塊兒渲染出來。未下載完的圖片需等下載完後才渲染。
④當css解析爲CSSOM後,html解析爲DOM後,二者將會結合在一塊兒生成Render Tree(渲染樹)。
⑤Layout(reflow): 計算出Render Tree每一個節點的形狀和位置。(很耗性能)
⑥Painting(repaint):瀏覽器繪製這些元素的樣式,顏色,背景,大小及邊框等。(很耗性能)
⑦Composite(層疊時):瀏覽器會將各渲染層的信息發送給GPU,GPU會按照合理的順序合併圖層而後顯示到屏幕上。(GPU合成圖像,單獨線程,更流暢,但耗內存)前端

 

理論知識(二):瀏覽器的渲染性能指標jquery

 大多數電腦顯示器的刷新頻率是60Hz,大概至關於每秒鐘重繪60次,由於小於這個頻率,頁面的渲染就會出現卡頓現象,影響用戶體驗。大多數瀏覽器都會對重繪操做加以限制,不超過顯示器的重繪頻率,由於即便超過那個頻率用戶體驗也不會有提高。所以,最平滑動畫的最佳循環間隔是1000ms/60,約等於16.6ms。該指標是遊戲開發中的最重要的指標。webpack

 

*前端加載優化:
·使用外聯CSS和JS:讓瀏覽器緩存,減小http請求。可利用webpack在引用的資源後面自動增長hash值,實現引用不變的基礎上對瀏覽器緩存的資源進行更新。對於緩存容量小的問題,能夠考慮緩存在localStorage。
·合併CSS、JS:減小http請求。
·按需加載:webpack的打包思路就是從程序邏輯入手:入口文件 => 分析代碼 => 找出依賴 => 打包,這樣代碼裏不引用的模塊就不可能被打進包裏,有效減小體積。
·按JS模塊加載:例如echart中若是隻用k線圖就只加載k線模塊。
·壓縮HTML、CSS、JS:減小資源大小。
·圖標採用base64:減小http請求。
·圖標採用雪碧圖(svg、font-icon):減小http請求,減小資源大小。
·圖片壓縮:picdiet(https://www.picdiet.com/zh-cn),是用JS編碼,無大小、尺寸、數量限制,默承認平均減小50%體積,清晰度基本沒損失,沒有兼容性問題,也能夠調節壓縮比。
·避免圖片和iFrame等的空src:減小http請求。
·圖片:滾屏懶加載。
·CDN加速:經常使用資源使用CDN加速提升資源響應速度,如jquery、echarts。(http://www.bootcdn.cn/)
·BigRender首屏渲染優化:html, js, css和圖片都放在textarea中懶加載(https://segmentfault.com/a/1190000006744741)。
·增長Loading進度條:將加載狀況呈現給用戶。web


*HTML、CSS結構優化:
·頁面的標籤越少,頁面的加載速度就越快,響應也更加迅速。
·css不能阻塞加載,因此將css放在頭部,防止白屏和重排重繪形成的內容閃爍現象。
·儘可能保持class的簡短,如:.box:nth-last-child(-n+1) .title,改成:.final-box-title。
·用flex佈局取代浮動佈局。
·移除空的CSS規則:空的CSS規則增長了CSS文件的大小,且影響CSS樹的執行。
·不聲明過多的font-size:過多的font-size引起CSS樹的效率。
·值爲0時不須要任何單位:爲了瀏覽器的兼容性和性能,值爲0時不要帶單位。
·display屬性會影響頁面的渲染,需合理使用:
①display:inline後不該該再使用width、height、margin、padding以及float
②display:inline-block後不該該再使用float
③display:block後不該該再使用vertical-align
④display:table-*後不該該再使用margin或者floatsegmentfault

*DOM性能優化:主要是防止重排和重繪
·圖片、音頻和視頻的寬高在加載完成以前爲0,因此靜態資源加載前需規定圖片的大小。
·儘可能避免重設圖片大小:屢次重設圖片大小會引起圖片的屢次重繪
·多使用requestAnimationFrame(待學習)
·若是同時添加父元素和子元素,要在內存中先將因此子元素添加到父元素下,將父元素一次性加入DOM樹。
·若是同時添加多個平級子元素,要先將平級子元素加入文檔片斷,再將文檔片斷總體加到頁面。具體爲:
①建立文檔片斷:var frag=document.createDocumentFragment();文檔片斷: 內存中臨時存儲多個平級子元素的虛擬父元素。
②將平級子元素,先追加到frag下: 用法同普通父元素
③將文檔片斷,總體添加到頁面
·先把dom節點display:none;(會觸發一次重排)。而後作大量的修改後,再把它顯示出來。
·clone一個dom節點在內存裏,修改以後;與在線的節點相替換。
·儘可能使用ID選擇器,ID選擇器是最快的。
·每次Dom選擇都要計算,緩存他,避免強制同步佈局(force reflow)。
·對於修改元素多個樣式,可使用cssText屬性,避免強制同步佈局。例如以下,觸發3次重排:
var el = document.getElementById('myDiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px';
改爲這樣,只需1次重排:
var el = document.getElementById('myDiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
將多個樣式變化定義到一個class中,再經過className添加class也行。
·動畫多使用transform和opacity,他們只會引發合成,不會引發佈局和重繪。
·若是圖層中某個元素須要重繪,那麼整個圖層都須要重繪。用translateZ(0)手動建立渲染層,減小需渲染的像素數,還能夠用GPU加速。可是不要濫用這個屬性,不然會大大增長內存消耗。(詳情:https://developers.google.cn/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas)
·不要使用table佈局,一個小改動會形成整個table的從新佈局。
·用css動畫而不是js動畫:css動畫有一個重要的特性,它是徹底工做在GPU上。由於你聲明瞭一個動畫如何開始和如何結束,瀏覽器會在動畫開始前準備好全部須要的指令;並把它們發送給GPU。而若是使用js動畫,瀏覽器必須計算每一幀的狀態;爲了保證平滑的動畫,咱們必須在瀏覽器主線程計算新狀態;把它們發送給GPU至少60次每秒。除了計算和發送數據比css動畫要慢,主線程的負載也會影響動畫; 當主線程的計算任務過多時,會形成動畫的延遲、卡頓。因此儘量地使用基於css的動畫,不只僅更快;也不會被大量的js計算所阻塞。
·減少複合層的尺寸:能夠將圖片的尺寸減小5%——10%,而後使用scale將它們放大;用戶不會看到什麼區別,可是你能夠減小大量的存儲空間。
·採用虛擬DOM技術:例如Vue、React等框架就採用了虛擬DOM。瀏覽器

*script優化:
·咱們知道腳本加載和運行會阻塞頁面,因此應該把<script>標籤放到最後。
·JS:throttle函數(節流):每XX秒內只執行一次;(https://segmentfault.com/a/1190000006722279)
·JS:debounce函數(防抖):當連續觸發函數調用時,在最後一次觸發的XX秒之後纔開始一次調用。(https://segmentfault.com/a/1190000006732819)
·對於多條件判斷,字典比if-else快。
·避免快速連續的佈局:
改善前:function resizeWidth() {
// 會讓瀏覽器陷入'讀寫讀寫'循環
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
改善後:var width = box.offsetWidth;
function resizeWidth() {
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = width + 'px';
}
}
·深刻原形鏈越深,搜索的速度就會越慢。記住,搜索實例成員的過程比訪問直接量或者局部變量負擔更重,因此增長遍歷原形鏈的開銷正好放大了這種效果。
·函數做用域鏈的搜索也會消耗性能,全局變量老是在做用域鏈的最後,因此耗時最久。最好儘量使用局部變量。一個好的經驗法則是:用局部變量存儲本地範圍以外的變量值。
·成員嵌套越深,訪問速度越慢。 location.href 老是快於window.location.href ,然後者也要比window.location.href.toString()更快。若是這些屬性不是對象的實例屬性,那麼成員解析還要在每一個點上搜索原形鏈,這將須要更長時間。
·計算簡化,如:for(var i=2;i<=Math.sqrt(n);i++){if(n%i==0){return false}}
·前面提到每幀的渲染應該在16ms內完成,但在動畫過程當中,因爲已經被佔用了很多時間,因此JavaScript代碼運行耗時應該控制在3-4毫秒。若是真的有特別耗時且不操做DOM元素的純計算工做,能夠考慮放到Web Workers中執行。緩存


*服務端設置優化:
·緩存一切可緩存的資源:http緩存。
·使用長Cache,避免304重定向:在移動端網絡不穩定的前提下,多一次請求,就多了一部分加載時間。
·使用DNS緩存:減小瀏覽器會在DNS解析中消耗的時間。
·啓用GZip:GZip是http協議的一部分,用來壓縮網頁大小的。
·圖片壓縮:默認生成縮略圖傳前端。
·減小Cookie:Cookie會影響加載速度,因此靜態資源域名不使用Cookie。
·域名解析:減小域名解析次數——減小跨站外部資源的引用。
·建立鏈接:減小鏈接建立次數——使用Keep-Alive避免重複鏈接。
·等待響應:提升服務器運行速度——提升數據運算及查詢速度。性能優化

相關文章
相關標籤/搜索