亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

前端性能優化

2024-04-27 15:09:25
字體:
來源:轉載
供稿:網友

工作中一個項目在運行時有一些性能問題,為此我看了很多與性能優化相關的內容,下面做個簡單的分享。

前端性能優化,這包括 CSS/JS 性能優化、網絡性能優化等等內容,這方面的內容 、 等等書都做了很多講解,強烈推薦閱讀。(這些書單參見本文結尾)

下面的內容,上面提到的書中大都包含了,因此可以考慮轉而去讀這些書,做一個完完全全的了解,對于本文,也就不要再讀下去了。

如果你堅持看到了這里,那就來談談我遇到的一些前端性能問題,并聊聊解決方案。

1 優先優化對性能影響大的部分

當應用有了性能問題后,不要一股腦扎到代碼中去,首先要想想那部分對性能影響最大。優先優化那些對性能影響大的部分,可以起到立桿見影的效果。

使用 Chrome DevTools ,可以很快地找到導致性能變差的最主要因素,關于 Chrome DevTools 的使用強烈推薦閱讀 Google Developers 上面的系列教程 - 。

另外在對代碼進行優化的時候,也首先要關注那些存在循環或者高頻調用的地方。有的時候我們可能不知道某個地方是否會高頻執行,比如某些事件的回調。這個時候可以使用 console.count 來對執行次數進行統計。當這部分高頻執行的代碼已經足夠優化的時候,就要考慮是否能夠減少執行次數。比如一個時間復雜度為 O(n*n*n) 的算法,再怎么優化也不如將其變為 O(n*n) 來的快。

2 對高頻觸發的事件進行節流或消抖

對于 Scroll 和 Touchmove 這類事件,永遠不要低估了它們的執行頻率,處理這類事件的時候可以考慮是否要給它們添加一個節流或者消抖過的回調。節流和消抖,可能其他人不這么翻譯,其實也就是 debounce 和throttle 這兩個函數。

debounce 和 throttle 是兩個相似(但不相同)的用于控制函數在某段事件內的執行頻率的技術。你可以在 underscore 或者 lodash 中找到這兩個函數。

2.1 使用 debounce 進行消抖

多次連續的調用,最終實際上只會調用一次。想象自己在電梯里面,門將要關上,這個時候另外一個人來了,取消了關門的操作,過了一會兒門又要關上,又來了一個人,再次取消了關門的操作。電梯會一直延遲關門的操作,直到某段時間里沒人再來。

所以 debounce 適合用在比如對用戶輸入內容進行校驗的這種場景下,多次觸發只需要響應最后一次觸發就好了。

2.2 使用 throttle 進行節流

將頻繁調用的函數限定在一個給定的調用頻率內。它保證某個函數頻率再高,也只能在給定的事件內調用一次。比如在滾動的時候要檢查當前滾動的位置,來顯示或隱藏回到頂部按鈕,這個時候可以使用 throttle 來將滾動回調函數限定在每 300ms 執行一次。

需要提到的是,這兩個函數常常被誤用,且很多時候當事人并沒有意識到自己誤用了。我曾經用錯過,也見過別人用錯。這兩個函數都接受一個函數作為參數,然后返回一個節流/去抖后的函數,下面第二種用法才是正確的用法:

1234567
// 錯誤的用法,每次事件觸發都得到一個新的函數$(window).on('scroll', function() {   _.throttle(doSomething, 300);});// 正確的用法,將節流后的函數作為回調$(window).on('scroll', _.throttle(doSomething, 200));

3 javaScript 很快,DOM 很慢

Javascript 如今已經很快了,真正慢的是 DOM。因此避免使用一些不易讀但據說能提高速度的寫法。不久前,一位朋友對我說使用 ‘+’ 號將字符串轉為數字比使用 parseInt 快。對此我并沒有懷疑,因為直覺上 parseInt 進行了函數調用,很可能會慢一些,我們一起在 node v6.3.0 上進行了一些驗證,結果的確如我們所預計的那樣,但是差別有多大呢,進行了 5 億次迭代,使用 + 號的方法僅僅快了2秒。雖然快了兩秒,但實際中將字符轉為數字的操作可能只會進行幾次,因此這樣的做法根本沒有意義,它只會讓代碼變得更難讀。

12
plus: 1694.392msparseInt: 3661.403ms

真正慢的是 DOM,DOM 對外提供了 API,而 JavaScript 可以調用這些 API,它們兩者就像是使用一座橋梁相連,每次過橋都要被收取大量費用,因此應該盡量讓減少過橋的次數。

3.1 為什么 DOM 很慢

談到這里需要對瀏覽器利用 HTML/CSS/JavaScript 等資源呈現出精彩的頁面的過程進行簡單說明。瀏覽器在收到 HTML 文檔之后會對文檔進行解析開始構建 DOM (Document Object Model) 樹,進而在文檔中發現樣式表,開始解析 CSS 來構建 CSSOM(CSS Object Model)樹,這兩者都構建完成后,開始構建渲染樹。整個過程如下:

在每次修改了 DOM 或者其樣式之后都要進行 DOM樹的構建,CSSOM 的重新計算,進而得到新的渲染樹。瀏覽器會利用新的渲染樹對頁面進行重排和重繪,以及圖層的合并。通常瀏覽器會批量進行重排和重繪,以提高性能。但當我們試圖通過 JavaScript 獲取某個節點的尺寸信息的時候,為了獲得當前真實的信息,瀏覽器會立刻進行一次重排。

3.2 避免強制性同步布局

在 JavaScript 中讀取到的布局信息都是上一幀的信息,如果在 JavaScript 中修改了頁面的布局,比如給某個元素添加了一個類,然后再讀取布局信息。這個時候為了獲得真實的布局信息,瀏覽器需要強制性對頁面進行布局。因此應該避免這樣做。

3.3 批量操作 DOM

在必須要進行頻繁的 DOM 操作時,可以使用  這樣的工具,它的思路是將對頁面的讀取和改寫放進隊列,在頁面重繪的時候批量執行,先進行讀取后改寫。因為如果將讀取與改寫交織在一起可能引起多次頁面的重排。而利用 fastdom 就可以避免這樣的情況發生。

雖然有了 fastdom 這樣的工具,但有的時候還是不能從根本上解決問題,比如我最近遇到的一個情況,與頁面簡單的一次交互(輕輕滾動頁面)就執行了幾千次 DOM 操作,這個時候核心要解決的是減少 DOM 操作的次數。這個時候就要從代碼層面考慮,看看是否有不必要的讀取。

4 優化渲染性能

瀏覽器通常每秒更新頁面 60 次,每一幀的時間就是 16.6ms,為了能讓瀏覽器保持 60幀 的幀率,為了讓動畫看起來流暢,需要保證幀率達到 60fps,因此每一幀的邏輯需要在 16.6ms 內完成。

每一幀實際上都包含下列步驟:

因此,通常 JavaScript 的執行時間不能超過 10ms。

JavaScript:改變元素樣式,添加元素到 DOM 中等等

Style:元素的類或者style改變了,這個時候需要重新計算元素的樣式

Layout:需要重新計算元素的具體尺寸

Paint:將元素的繪制的圖層上

Composite:合并多個圖層

當然也不是說每一幀都會進行這些操作。當你的 JavaScript 改變了某個 layout 屬性,比如元素的 width 和height 或者 top 等等,瀏覽器就會重新計算布局,并對整個頁面進行重排。

如果修改了 background、color 這樣的僅僅會讓頁面重繪的屬性,這不會影響頁面的布局,瀏覽器會跳過計算布局(layout)的過程,只進行重繪(paint)。

如果修改了一個不需要計算布局也不需要重繪的屬性,那就只會進行圖層的合并,這是代價最小的修改。從 上你可以知道修改那些樣式屬性會觸發(Layout,Paint,Composite)中的那些操作。

4.1 將漸變或者會動畫元素放到單獨的繪制層中

繪制并非在一個單獨的畫布上進行的,而是多層。因此將那些會變動的元素提升至單獨的圖層,可以讓他的改變影響到的元素更少。

可以使用 CSS 中的 will-change: transform; 或者 transform: translateZ(0); 這樣來將元素提升至單獨的圖層中。

在調試的時候你可以在 Chrome DevTools 的 timeline 面板來觀察繪制圖層。當然也不是說圖層越多越好,因為新增加一個圖層可能會耗費額外的內存。且新增加一個圖層的目的是為了避免某個元素的變動影響其他元素。

4.2 降低繪制復雜度

某些屬性的重繪相對而言更加復雜,比如 filter、box-shadow 等濾鏡或漸變效果。因此不要濫用這類效果。

5 優化 JavaScript 的執行

下面提到的 JavaScript 優化,并不是說如何讓 JavaScript 執行的更快,而是如何讓 JavaScript 更高效地與 DOM 配合。

5.1 使用 requestAnimationFrame 來更新頁面

我們希望在每一幀剛開始的時候對頁面進行更改,目前只有使用 requestAnimationFrame 能夠保證這一點。使用setTimeout 或者 setInterval 來觸發更新頁面的函數,該函數可能在一幀的中間或者結束的時間點上調用,進而導致該幀后面需要進行的事情沒有完成,引發丟幀。

requestAnimationFrame 會將任務安排在頁面重繪之前,這保證動畫能有足夠的時間來執行 JavaScript 。

5.2 使用 Web Worker 來處理復雜的計算

JavaScript 是在單線程的,并且可能會一直這樣,因此 JavaScript 在執行復雜計算的時候很可能會阻塞線程,導致頁面假死。但 Web Worker 的出現,以另外一種方式給了我們多線程的能力,可以將復雜計算放在 worker 中進行,當計算完成后,以 postMessage 的形式將結果傳回來。

對于單個函數,因為 Web Worker 接受一個腳本的 url 作為參數,使用 URL.createObjectURL 方法,我們可以將一個函數的內容轉換為 url,利用它創建一個 worker。

12345678910111213141516
var workerContent = `self.onmessage = function(evt){    // ...    // 在這里進行復雜計算    var result = complexFunc();    // 將結果傳回    self.postMessage(result);};`// 得到 urlvar blob = new Blob([workerContent]);var url = window.URL.createObjectURL(blob);// 創建 workervar worker = new Worker(url);

5.3 使用 transform 和 opacity 來完成動畫

如今只有對這兩個屬性的修改不需要經歷 layout 和 paint 過程。

6 優化 CSS

CSS 選擇器在匹配的時候是由右至左進行的,因此最后一個選擇器常被稱為關鍵選擇器,因為最后一個選擇越特殊,需要進行匹配的次數越少。要千萬避免使用 *(通用選擇器)作為關鍵選擇器。因為它能匹配到所有元素,進而倒數第二個選擇器還會和所有元素進行一次匹配。這導致效率很低下。

12
/* 不要這樣做 */div p * {}

另外 first-child 這類偽類選擇器也不夠特殊,也要避免將它們作為關鍵選擇器。關鍵選擇器越特殊,瀏覽器就能用較少的匹配次數找到待匹配元素,選擇器性能也就越好。

還有一個老生常談的注意事項,不要使用太多的選擇器。如果還有同學很悲劇地要兼容低版本 IE,要避免使用 CSS 表達式,它的性能很差,詳細內容可參見我之前記錄的一篇筆記 (Https://Github.com/wy-ei/notebook/issues/15 )

7 合理處理腳本和樣式表

如今有了 requirejs,webpack 等工具,可能很少會在頁面中加載很多 JavaScript/CSS代碼了。盡管如此,還是有必要談談如何合理處理腳本和樣式表。

大多數人已經知道通常要把 JavaScript 放在文檔底部,把 CSS 放在文檔頂部。為什么呢?因為 JavaScript 會阻塞頁面的解析,而外部樣式表會阻塞頁面的呈現和 JavaScript 的執行。

7.1 CSS阻塞渲染

通常情況下 CSS 被認為是阻塞渲染的資源,在CSSOM 構建完成之前,頁面不會被渲染,放在頂部讓樣式表能夠盡早開始加載。但如果把引入樣式表的 link 放在文檔底部,頁面雖然能立刻呈現出來,但是頁面加載出來的時候會是沒有樣式的,是混亂的。當后來樣式表加載進來后,頁面會立即進行重繪,這也就是通常所說的閃爍了。

7.2 JavaScript阻塞文檔解析

當在 HTML 文檔中遇到 script 標簽后控制權將交給 JavaScript,在 JavaScript 下載并執行完成之前,都不會解析 HTML。因此如果將 JavaScript 放在文檔頂部,恰好這個時候 JavaScript 腳本加載的特別慢,用戶將會等待很長一段時間,這段個時候HTML 文檔還沒有解析到 body 部分,頁面會是空白的。

另外常常被忽略的事實是:在瀏覽器沒有下載并解析完成使用 link 引入的 CSS 文件之前,JavaScript 是不會執行的,因為 JavaScript 中可能需要讀取樣式,而此時樣式表還沒有加載回來,因此瀏覽器不會執行 JavaScript。可以給 JavaScript 加上 async 標記,表示 JavaScript 的執行不會讀取 DOM ,JavaScript 可以不被 CSS 阻塞,可以在空閑時間立刻執行。

綜上所述,你更要保證 CSS 文件加載的足夠快。

關于這部分內容,  上有很精彩的講解,墻裂推薦?!陡咝阅芫W站建設指南》我在讀的時候記錄了筆記,可以在看到。

最后強烈推薦閱讀 Google Developers 中關于性能優化的(https://developers.google.com/web/fundamentals/performance)。

原文鏈接:http://www.kubiji.cn/juhe-id7101.html


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97超碰色婷婷| 亚洲精品一区av在线播放| 精品中文字幕在线| 欧美性猛交xxxx免费看| 色综合久久中文字幕综合网小说| 超碰精品一区二区三区乱码| 国产精品美女久久久免费| 精品高清一区二区三区| 国产成人精品久久二区二区| 欧洲成人免费aa| 亚洲图片欧美日产| 亚洲iv一区二区三区| 欧美日韩一区二区免费在线观看| 日韩精品极品视频免费观看| 欧美成人精品不卡视频在线观看| 亚洲欧洲日本专区| 中文字幕日韩有码| 久久久噜噜噜久久中文字免| 欧美日韩一区免费| 久久久成人精品视频| 国模视频一区二区三区| 91在线无精精品一区二区| 国产精品久久久一区| 国产一区二区三区视频免费| 欧美亚洲激情视频| 97在线视频国产| 神马久久桃色视频| 日韩高清av一区二区三区| 亚洲女人天堂色在线7777| 尤物99国产成人精品视频| 国产成人精品av| 日韩欧美国产免费播放| 久久中文字幕在线| 在线色欧美三级视频| 国内精品久久久久伊人av| 国产在线不卡精品| 97视频网站入口| 51视频国产精品一区二区| 秋霞成人午夜鲁丝一区二区三区| 亚洲国产精品人久久电影| 成人欧美在线视频| 国产精品老女人精品视频| 国产精品福利久久久| 精品国内产的精品视频在线观看| 日韩电视剧在线观看免费网站| 懂色aⅴ精品一区二区三区蜜月| 久久影视电视剧免费网站清宫辞电视| 欧美日韩国产一区中文午夜| 日本一区二区不卡| 久久亚洲精品国产亚洲老地址| 91精品在线国产| 亚洲天堂av图片| 奇米影视亚洲狠狠色| 国产精品免费网站| 久久久久久久久国产精品| 欧美日韩国产专区| 欧美日韩国产一区二区三区| 欧美日韩在线视频一区| 亚洲男人天堂2019| 91精品啪aⅴ在线观看国产| 欧洲s码亚洲m码精品一区| 国内精品久久久久伊人av| 欧美成人午夜激情视频| 日本精品中文字幕| 亚洲色图激情小说| 在线播放国产精品| 欧美日韩国产精品一区二区不卡中文| 日韩精品在线免费观看视频| 国内外成人免费激情在线视频| 欧美日韩在线视频一区| 欧美日韩一区二区在线播放| 黄色成人av网| 国内精品一区二区三区| 欧美日韩中国免费专区在线看| 国产精品wwwwww| 欧美老女人bb| 久久久国产精彩视频美女艺术照福利| 日韩69视频在线观看| 蜜臀久久99精品久久久无需会员| 久久久亚洲天堂| 日本不卡高字幕在线2019| 欧美日韩加勒比精品一区| 高清亚洲成在人网站天堂| 中文字幕在线亚洲| 亚洲成人精品久久久| 69国产精品成人在线播放| 欧美一区二三区| 亚洲天堂av电影| 亚洲人成电影在线播放| 日韩精品久久久久| 国产一区二区三区视频| 欧美激情精品在线| 色偷偷av一区二区三区乱| 深夜福利日韩在线看| 亚洲娇小xxxx欧美娇小| 国产成人avxxxxx在线看| 亚洲a区在线视频| 日韩精品在线看| 国产亚洲在线播放| 日韩精品在线看| 色妞久久福利网| 精品久久久久久亚洲精品| 亚洲肉体裸体xxxx137| 亚洲女人天堂av| 亚洲在线视频观看| 日韩最新免费不卡| 亚洲第一视频网站| 91av中文字幕| 日韩av不卡电影| 国产精品高潮呻吟久久av无限| 国产一区二区三区四区福利| 亚洲第一偷拍网| 久久人人爽人人爽人人片av高请| 亚洲欧美成人在线| 色综合久久中文字幕综合网小说| 国产精品亚洲精品| 精品视频在线观看日韩| 国产精品18久久久久久麻辣| 在线观看精品国产视频| 欧美性感美女h网站在线观看免费| 欧美大片在线免费观看| 4438全国亚洲精品在线观看视频| 欧美丰满少妇xxxxx做受| 久久久视频精品| 国产99在线|中文| 久久综合伊人77777蜜臀| 91精品国产91久久| 午夜精品视频网站| 在线观看成人黄色| 欧美日韩裸体免费视频| 欧美日韩亚洲激情| 米奇精品一区二区三区在线观看| 狠狠做深爱婷婷久久综合一区| 性欧美激情精品| 久久久久久久久久久免费精品| 欧美日韩福利电影| 久久精品一本久久99精品| 亚洲欧美日韩区| 日韩a**站在线观看| 7m第一福利500精品视频| 久久不射热爱视频精品| 欧美富婆性猛交| 欧美激情一区二区三区在线视频观看| 午夜精品福利视频| 欧美成年人网站| 日本免费一区二区三区视频观看| 亚洲精品suv精品一区二区| 久久久久久国产精品三级玉女聊斋| 国产精品一区久久| 久久精品久久久久电影| 成人免费视频在线观看超级碰| 亚洲一区二区三区在线免费观看| 久久中文字幕在线视频| 亚洲自拍偷拍在线| 欧美色欧美亚洲高清在线视频| 久久影视电视剧免费网站清宫辞电视| 亚洲资源在线看| 国产精品igao视频| 日韩精品日韩在线观看| 日韩美女免费观看| 精品亚洲国产视频| 国产黑人绿帽在线第一区| 欧美性xxxx极品高清hd直播| 国产美女精品视频免费观看|