前端性能優化小結

  1. http優化,加大併發,減小請求數量以及傳輸量
  • domain hash技術突破併發限制。http1.x瀏覽器對於發起的鏈接有併發限制,這個限制是針對域名的,因此將靜態資源放在多個不一樣的域名下,也能夠突破這個限制。可是也不宜使用太多域名。會增長額外的dns解析成本。
  • 合理使用http頭。使用expires,cache-control,Etags等http頭緩存靜態資源。這篇文章介紹的很詳細:https://zhuanlan.zhihu.com/p/...
  • Connection:keep-alive。保持tcp鏈接。避免三次握手以及tcp的慢啓動開銷。
  • 合理利用空閒時間作一些預操做。預測用戶的大機率行爲,在頁面空閒時加載後續所須要的資源。dns預解析。TCP預鏈接。頁面預渲染。有一些標籤屬性已經能夠很好的作到這些,如prefetch & preload & dns-prefetch。
  • 合併css,js文件。
  • 圖片壓縮以及頁面須要多大的圖片就請求多大的圖片。好比頁面只顯示20*20的圖片,就不要返回一個500*500的圖片。
  • cdn加速。
  • gzip壓縮。
  • 減小沒必要要的通訊量,好比合併發送上報數據。
  • 按需加載模塊資源。好比js,css。
  • 使用http2。
  1. 緩存請求,並保持緩存內容大小與性能之間的平衡。好比某個請求涉及大量的數據庫操做,耗時很長,而且有必定機率屢次請求。在這個數據的實時性和重要性不是那麼強的狀況下,咱們能夠將請求結果緩存到變量中或瀏覽器的一些別的存儲機制中。可是緩存內容過多也會對性能有影響,因此咱們也要根據必定的規則(好比訪問頻率,訪問前後時間,緩存總數量等)及時地清除部分緩存。若是不想改動代碼,那麼http響應能夠返回Expires http請求頭,在過時以前就再也不發請求。
  2. cookie優化,減小cookie傳輸量
  • 避免cookie太龐大。不要什麼都往cookie上放。cookie的主要做用在於身份識別,而不是信息存儲。由於每一個請求都會帶着cookie,無形中會加大不少傳輸量。前端的話可使用一些其餘的替代存儲方式。好比localStorage,sessionStorage。
  • cookie free技術。將一些靜態資源放在與主域不一樣域名的服務器上,瀏覽器請求的時候就不會帶上主域的cookie了,從而減小傳輸量。
  1. Bigpipe技術。產生於Facebook公司的前端加載技術,它的提出主要是爲了解決重數據頁面的加載速度問題,是一種數據漸進式預加載方案,基於HTTP Chunk。
  2. PWA技術。service worker。
  3. 避免空的src和href。
  4. 圖片懶加載。lazy load。
  5. 腳本加載優化
  • script標籤放到頁面最後,</body>標籤前面,避免阻塞頁面渲染。一個討論:https://www.zhihu.com/questio...
  • 合併,壓縮腳本。減小鏈接數和數據傳輸大小。
  • 無阻塞的腳本css

    • script標籤添加defer,async屬性。
    • 動態生成script標籤。使用onload事件或onreadystatechange事件來檢測腳本加載完從而執行加載完以後的回調。
    • 使用ajax方式加載js內容。插入一個script標籤中。好處是加載完以後不會當即執行。
  1. JS數據存取
  • 減小做用域查詢。做用域鏈的查詢,變量的位置越深,查詢速度越慢。而全局變量在做用域鏈最深。因此,對於使用一次以上的跨做用域變量咱們應該把它用局部變量存起來。
  • 避免內存泄露。html

    • 循環引用
    • IE,閉包中有dom對象。
  • 減小嵌套成員的查找。可緩存在局部變量中。相似var Dom = YAHOO.util.Dom;
  • 減小原型鏈查找。
  1. dom優化
  • 減小dom數量。若是頁面dom數量太多,對性能是有影響的。
  • 減小dom訪問與修改。dom與JavaScript至關於兩個獨立的部分以功能接口鏈接,會帶來性能損耗。
  • 儘可能不要在循環中更新頁面內容。一個更有效率的版本將使用局部變量存儲更新後的內容,在循環結束時一次性寫入。
  • 不建議用數組的 length 屬性作循環判斷條件。訪問集合的 length 比數組的length 還要慢,由於它意味着每次都要從新運行查詢過程。
  • 使用快的API。好比document.querySelector()。
  • 事件綁定。前端

    • 多使用事件代理,而不是每一個dom節點上去都綁定事件。
    • 考慮使用自已定義的事件管理器,一個dom上不要反覆綁定事件。而是維護一個事件回調數組,像jQuery作的那樣。
  • 減小回流與重繪。css3

    • 少使用.style一個屬性一個屬性地去改。而是合併到一塊兒一塊兒修改。好比用class來控制樣式,或者cssText來批量修改。
    • 讓要操做的元素進行"離線處理",處理完後一塊兒更新。
    • 迴流必將引發重繪,而重繪不必定會引發迴流。
    • 減小對位置信息的屬性讀取以及getComputedStyle與currentStyle的使用。瀏覽器會維護1個隊列,把全部會引發迴流、重繪的操做放入這個隊列,等隊列中的操做到了必定的數量或者到了必定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓屢次的迴流、重繪變成一次迴流重繪。若是代碼中頻繁讀取實時位置屬性,會致使瀏覽器屢次重排。引發性能問題。
  1. 異步優化任務。分割任務異步執行,讓出線程。
  • 若是用戶的操做100ms得不到響應,用戶就會感受到與應用失去聯繫。若是咱們的代碼執行時間太長,用戶其餘的操做得不到響應。因此若是咱們沒法減小腳本執行時間,咱們可能考慮主動地讓出線程。分解任務,異步執行。

好比分解成多個任務使用setTimeout或setInterval來異步執行。git

  • 可是若是咱們任務分得太細,好比每一個循環體算成一個任務,每一個任務結束就讓出線程,效率就很低了,由於setTimeout 和 setInterval 原本就設計的慢吞吞的,即便延時時間爲0,瀏覽器環境下每秒也最多執行幾百次。而換成while循環,每秒能執行幾百萬次。 因此咱們每一個異步任務中應該多處理一些任務,好比咱們讓它執行50ms。在每一個異步中檢測一下執行時間,加入while循環,時間若是小於50ms就繼續執行,超過50ms就讓出線程。這樣既保證了不阻塞線程,也讓咱們的任務能儘快地完成。
  • 使用Web Workers。
  1. ajax的優化。目前一些比較成熟的庫的ajax都是在ajax徹底接收完響應以後才執行成功的回調。這裏其實有很大的優化空間。
  • 通常的ajax封裝是在XMLHttpRequest的readyState==4(整個請求過程已經完畢)的時候進行成功回調處理。而其實在readyState==3的時候(響應體下載中,responseText中已經獲取了部分數據.)已經能夠對已經接收到的部份內容進行處理了。好比幾十萬條數據從後端傳過來,要插入dom。若是咱們等到全部數據接收完畢,再一次性插入dom,可能會有很大的性能問題。可是若是咱們在後臺將數據以必定的方式拼裝,而後前端接收到一部分處理一部分,就有兩方面的性能提高,一方面是提早處理了數據,讓用戶能夠更早地看到數據效果,另外一方面是分解了任務。
  • 合併請求。好比多個圖片base64格式加分割符一塊兒發送過來。前端再把結果分割,分發到多個img標籤上去。
  • 數據傳遞格式。不必定非要是json格式。其實能夠很靈活。自定義的格式一方面能夠減小數據傳輸量,另外一方面更方便前端邊接收邊處理。
  1. 循環與遞歸
  • 尾調用優化。會將從內存中清除前面的調用棧,將調用棧清零。一方面是內存釋放,另外一方面是避免了調用棧溢出引發的錯誤。
  • 減少循環次數。每一個循環體中多執行幾個循環內容。
  • 減小循環體開銷。好比使用倒序循環。
  • 緩存計算結果。使用Memoization技術來避免重複計算。
  1. 函數的節流與防抖,限制函數主體執行頻率。頻繁執行某些函數會嚴重影響性能,好比一些常見的觸發頻率很高的瀏覽器事件,若是每次觸發都去執行回調甚至操做dom,性能影響很大,而且咱們肉眼對dom變化的實時性要求並無那麼高。因此須要限制主體內容的執行頻率。工具庫underscore中提供了對應的_.throttle和_.debounce方法。
  • window對象的resize、scroll事件
  • 拖拽時的mousemove事件
  • mousedown、keydown事件
  • 文字輸入、自動完成的keyup事件
  1. requestAnimationFrame方法。
  2. 邏輯優化,減小耗時操做。不少功能並非只有一種途徑去實現。若是一種操做特別耗時。也許能夠優化一些邏輯就減小這樣的操做。
  3. 定時器的控制。

應用中存在過多的定時器會影響性能。特別是單頁應用中,若是咱們定義了一些定時器而沒有隨着場景消失而清掉定時器,還可能會產生不少邏輯上的問題。github

  1. 正則表達式優化。
  2. css gpu加速。

歡迎補充交流。github地址:https://github.com/liusaint/l...ajax

參考:
相關文章
相關標籤/搜索