提高現代web app中頁面性能

提高現代web app的中的頁面性能

前言,本文翻譯自https://docs.google.com/presentation/d/1hBIb0CshY9DlM1fkxSLXVSW3Srg3CxaxAbdocI67NCQ/edit#slide=id.g32e52b1ea6_1_0看到以後感受講解的系統清晰明瞭,實屬一篇好文。就加上本身的理解翻譯了一下,聊以加深印象。
css

硬件、網絡,對性能的而言始終不能避開的兩個物理因素

1、 硬件如何影響性能

硬件(即處理能力)決定了計算密集型任務的表現
瀏覽器必須解析、編譯並執行全部的js,以下如所示:

對於每一個階段而言,代碼量的差別顯然會影響其變現即影響性能,這種差別在低處理能力的機器上的體現尤其明顯。
固然其餘類型的資源請求也會影響性能,相比之下js的影響是比較突出的。
因此考慮不一樣用戶cpu的情況,減小js怪物(即縮小js體積)是很必要的。能夠從如下幾方面着手:html

  1. 刪除沒必要要js
  2. 延遲加載非關鍵js
  3. 藉助相關工具webpack

    1.1 刪除沒必要要js

    只在必要的時候進行轉換

    僅僅對須要ES5的客戶端才進行轉換,80%的瀏覽器已經支持ES2015。(結合本身實際開發狀況,移動端而言確實80%+的手機已經支持ES2015,僅僅只遇到oppop,vivio這兩中手機不支持。)由於轉換以後的代價仍是有的,以下所示:git

//ES2015
books.map(b => b.title);
//ES5
books.map(function(b) { return b.title; }, this);
//體積大了一倍

使用壓縮工具/優化工具

像UglifyJS & Closure Compiler 之類的工具,在壓縮以外還有一些優化功能。
對大多數的js而言壓縮代碼中空格移除和符號修改佔了95%的工做量,並不是是精心的代碼轉換。
壓縮不該該是盲目的,應該平衡下面幾點。github

  • 更好的壓縮比
  • 高額的計算機資源消耗
  • 前期準備
  • 可能的反作用
    壓縮可能不是一味的追求體積更小,相對而言,壓縮也應該權衡一下其餘方面。比較常見就是代碼壓縮時相比於其餘流程,超長的時間消耗。壓縮以後可能遇到關鍵字的問題。
    如何解決其實應該是從自己項目出發。
  • 儘量的優化可緩存的靜態資源
  • 在壓縮體積和時間之間找到一個平衡點

使用tree-shaking移除沒用的代碼

和壓縮代碼的目的一致,減少資源大小,不過是從另外一個層面的解決方案。像webpack,rollup都提供了該功能。
tree-shaking會將沒有被用到的exports移除web

//tool 
//used
export function a(){
    console.log('1')
}
export function b(){
    console.log('2')
}
//app.js
import {a} from './tool'
a()

function b 未被使用,最終的打包文件中b將會被刪除。瀏覽器

ES2015的模塊是靜態的,可使用tree-shaking

import/export 在執行以前就被肯定,而且二者只能在頂層,沒有條件邏輯的狀況下使用(畢竟未執行)緩存

tree-shaking的侷限

  • 僅僅刪除未被使用的導出
  • 不支持全部的代碼庫(僅僅ES2015)
  • 可能作不到極致
    難以肯定刪除是否會有反作用,這種打包器只能保留

自我排查

工具不能作到盡善盡美,而且在執行以前肯定某項問題是困難的。
當前來講應該從代碼規範和代碼註釋來自我完善。服務器

對於框架

若是非必須,請不要使用。大的框架至少300kb的體積。
固然必要,請基於下面幾點來選擇:網絡

  • 服務端渲染
  • 懶加載
  • 代碼優化
  • 性能

1.2 延遲加載非必需js

先看一下js不一樣引入方式的差異

默認方式 Async Defer
阻塞渲染
執行時機 加載完成 加載完成 document解析完成

使用代碼分割和懶加載

  • 減小啓動時須要加載的js
  • 儘量少的加載不相關的js
    傳統的作法是加載Bundle js,代碼分割是將代碼分紅不一樣的chunk
    這裏一樣有兩種極端:
  • 每一個模塊對應一個js
    很差壓縮
    利於緩存
    粒度更小
  • 整個應用只對應一個js
    便於壓縮
    不利於緩存
    粒度太大,便可維護性
    突然有種中庸的感受了,凡事皆有度,全部單一操做都不能過度苛求極致,兼顧纔是合理

    1.3 使用其餘工具

    使用html和css

    某些情況下可能須要vanilla JS(即原生js),框架帶來便利的同時不可避免的有其餘的一些性能消耗。提到這裏有一篇文章你們能夠看一下我是怎麼把個人 React 應用換成 VanillaJS 的(這是否是一個壞主意)
    舉個例子:
    Netflix 下降了他們登陸頁50%的TTI(傳輸時間間隔)經過下面的方式:
  • 使用原生js來代替React
  • 當用戶登陸的時候加載餘下的部分

使用server

將代價昂貴的庫放到server端,使用ssr來代替client-side-render.
ssr能夠將咱們初始頁面加載事件減小到原來的1/5並減小不一樣瀏覽器之間的差別。
ssr確實首屏的優化確實很大,優勢很少說。但這裏提一句,不要盲目ssr,特別是初次請求響應時間較長的接口

2、網絡的影響

首先了解兩個概念:

  • 帶寬: 數據吞吐量(比特/秒)
  • 延遲: 延遲數據傳輸時間(ms)

對於大部分市場來講,帶寬是能夠知足需求的(這裏統計是國外的,平均26兆,國內略低一點),平均頁面大小3.5Mb。傳輸時間(3.5/26)0.13s。國內會差一點。
延遲對性能影響比較明顯。
移動網絡的延遲

網絡 延遲ms
5G <=4
4G <=100
3G 100-500
3G 300-1000

適應移動網絡的限制

應該從下面幾方面來分別考慮。

  • 減小請求數量
  • 優化關鍵路徑
  • 減小請求大小

2.1 減小請求數量

新建一次鏈接的代價是昂貴的,要重複如下過程

創建鏈接須要1至3+響應在數據相應以前。

  1. DNS 查詢(可能)
  2. TLS 握手(可能)
  3. 請求資源

初始狀態鏈接不能被充分利用

TCP slow-start限制了在初始響應裏裏數據被髮送的數量

發送更多的數據一般狀況下比新建鏈接要划算。

請求的體積與相應時間並非線性關係。
兩次50k的請求消耗比一次100k的大了很多。

減小重定向的使用

  • 重定向增長了服務器昂貴的循環
  • server-side 相對於client-side來講重定向優秀一點(快而且可緩存)
  • 看一下301和302的響應code

使用緩存

理想狀態下,確實資源是否最新不該該經過網絡請求
能夠經過下面的方式:

  • 使用Content-addressed URLs:
    即內容與地址對應,log13234d.jpg而非log.jpg
  • 使用max-age

這種瀏覽器調整爲Facebook節省了60%的請求

使用service workers來加強緩存

service worker能夠幫組咱們:

  • 攔截網絡請求
  • 訪問瀏覽器緩存
  • 代替發送網絡請求來處理過時的資源

使用http2

使用HTTP2時,每一個來源只須要一個鏈接,減小了鏈接建立的開銷。

2.2 優化關鍵路徑

優化頁面渲染或者加載時所需的事件以便儘量的加快完成。

瀏覽器優化資源請求

對於全部的請求,瀏覽器對其是有權重處理的,即分不一樣的優先級來加載。具體來講就是重要會阻塞渲染的優先級比較高。
以下圖所示:

使用資源提示

經過如下方式,提早加載或者請求將要用到的內容:

  • Dns-prefresh
  • preconnect
  • Preload(當前頁面)
  • Prefetch(下個頁面)

2.3 下降請求大小

  • 使用Brotli壓縮
    相對於gzip
    更好的壓縮比,文件越大越明顯
    更快的解壓縮
    壓縮速度極大提高
  • 減小js體積
  • 優化圖片
    23就再也不多提了,方式有不少。

結束語

對於好的資源,多讀收益仍是很明顯的。此次翻譯感受體會又多了一些,不過因爲本人才疏學淺,若有錯誤還望多多指正。一言概之,共同窗習。更多請移步

相關文章
相關標籤/搜索