前端性能優化策略

注意: 最好是在修改以後進行先後對比,在使用了優化方法以後和沒使用的時候,由於就算使用了優化方式,也不必定會起到性能優化的效果,須要據場景而定。css

http 請求過程中潛在的性能優化點

  • 靜態資源通常放到 cdn 加快靜態資源的得到,可是當咱們 cdn 的域名和頁面的域名相同的時候,請求會帶上不準不須要的 cookies ,因此二者的域名不能同樣。
  • dns 緩存, 下降訪問 dns 的時間。
  • 對於接口,咱們能夠減小 http 請求的次數和大小。
  • 瀏覽器緩存。
  • 頁面渲染過程優化。
  • 使用服務端渲染。

資源壓縮與合併

在真實的開發中都是使用構建工具(webpack、gulp等)來完成下面的事情html

html 壓縮

去掉空格、註釋、回車、換行。html5

  • 使用在線網網站進行壓縮(實際公司中不適用)。
  • 使用 nodejs 提供的 html-minifier
  • 後端模板引擎渲染壓縮。

css 壓縮

去掉空格、註釋、回車、換行無效代碼刪除語義合併。node

  • 使用在線網網站進行壓縮(實際公司中不適用)。
  • 使用 nodejs 提供的 html-minifier
  • 使用clean-cscss進行壓縮。

js壓縮與混亂

無效字符的刪除、剔除註釋、代碼語義的縮減和優化(如變量名縮短)、代碼保護(將Js代碼混亂,使其不可讀)。webpack

  • 使用在線網站進行壓縮。
  • 使用html-minifier
  • 使用uglifyjs2js進行壓縮 。

文件合併

文件合併能夠減小網絡請求, 並且瀏覽器可以同時併發的請求數量有限,當請求過多的時候可能須要等待,文件合併能夠減小請求次數,減小等待。可是存在首屏渲染問題(第一次請求時間長)、緩存失效(單個文件的緩存失效會致使合併當中其餘文件的緩存失效)的問題。因此有以下的合併建議。ios

  • 公共庫合併: 公共庫通常不會變,咱們能夠將它們進行合併。
  • 不一樣頁面的合併: 針對單頁應用,只有當咱們跳轉到那個頁面的時候,纔去請求這個頁面的資源,將這個頁面涉及的資源進行合併。

那麼怎麼進行文件合併呢?以下:web

  • 使用在線網站進行文件合併。
  • 使用nodejs實現文件合併。

圖片優化

每種圖片格式都有本身的特色,針對不一樣的業務場景選擇不一樣的圖片格式很重要gulp

  • jgp有損壓縮
  • png: 顏色類型豐富的圖片,應該選擇位數高的pngsegmentfault

    • png8: 256色,支持透明
    • png24: 2^24色 不支持透明
    • png32: 2^24色 支持透明

不一樣格式圖片經常使用的業務場景

  • jpg有損壓縮,壓縮率高,不支持透明: 大部分不須要透明圖片的業務場景
  • png支持透明,瀏覽器兼容好: 大部分須要透明圖片的業務場景
  • webp壓縮程度更好,在ios webview有兼容性問題: 安卓所有
  • svg矢量圖,代碼內嵌,相對較小,圖片樣式相對簡單的場景: 圖片樣式相對簡單的業務場景

圖片壓縮

  • 可以使用tinypng這個網站來壓縮

css 雪碧圖

把網站上用到的一些圖片整合到一張單獨的圖片當中,從而減小大量的 http 請求的數量。缺點是圖片會變大後端

  • 第一步是將圖片合併到一張圖片上
  • 第二步是使用在線網站,上傳圖片,選中指定的圖片,而後會有相應的css

Image inline

將圖片內嵌到html當中, 減小網站的 http 請求數量, 如使用 base6 的方式插入圖片, 通常網站當中一些小的圖標能夠用它,實際根具狀況而定

使用矢量圖

使用 svg 進行矢量圖的繪製,圖片的質量和速度都特別好,使用得也比較多。

寄予頁面渲染過程的優化

https://segmentfault.com/a/11...

併發

瀏覽器對於一個域名的併發請求數量是有限的,因此咱們須要設置多個域名,好比 cdn 設置多個域名

懶加載和預加載

懶加載

  • 通常都是對於圖片來講,當圖片進入可視區域的時候再加載圖片
  • url 地址放置到 img 標籤當中,當進入可視區的時候,將其取出來設置

預加載

  • 圖片等靜態資源在使用以前的提早請求
  • 資源使用到的時候從緩存當中加載

有三種方式:

  • 直接在頁面上把 img 標籤放到前面, 而後 display: none;
  • var image = new Image(); image.src = xxxx; 使其下載下來,後面使用的時候後會直接去緩存拿
  • 使用XMLHttpRequset, urlimage.srcurl, 可使用它更加精細的對預加載的過程進行控制
  • 使用preload.js

客戶端存儲

Cookie

用來維護用戶狀態

  • Cookie的生成方式: 服務端的response.header使用set-cookie, 或者使用document.cookie進行讀寫
  • 瀏覽器端在相應的域名下保存

cdn的靜態資源不須要cookie, 可是在相同域名下面,http請求會自動帶上cookie, 解決辦法是cdn的域名和主站的域名要不相同。

localstorage

對於不會常常變得數據,能夠存在裏面

  • html5當中設計出來專門用於瀏覽器存儲的
  • 大小爲5M左右
  • 瀏覽器緩存方案

sessionStorage

  • 會話級別的瀏覽器存儲(一個tab)
  • 大小爲5M左右
  • 如使用它進行表單信息的維護(提高用戶體驗)

IndexedDB

  • 用於客戶端存儲大量結構化數據
  • 爲應用建立離線版本

Service Workers

能夠啓動一個其餘的線程來進行運算, 防止阻塞。

  • 使用攔截和處理網絡請求的能力去實現離線應用
  • 使用那個Service worker在後臺運行同時能和頁面通訊的能力。
  • 存儲對應於瀏覽器當中的cache

PWA

是一個 web app 新模型

瀏覽器自動緩存

須要response-headerrequest-header進行配合,每一個文件在進行緩存存儲的時候,都會將response-header一塊兒存,方便下一次判斷緩存狀況時使用response-header當中和緩存相關的頭字段。並且若是是直接從緩存當中讀取。

命中max-age、expire緩存策略的狀態碼爲200, 命中etag、last-modified、s-maxage緩存策略的時候狀態碼爲304
響應頭當中的和緩存相關的頭字段以及狀態碼,都須要咱們在服務端判斷是否爲響應的狀況後,手動設置

Cache-Control

可存在於requset-headerresponse-header

  • max-age : 再這個時間以內,再次請求相同資源的時候,瀏覽器會直接從緩存中取,不會發起請求,狀態碼爲200
  • s-maxage: 優先級高於max-age, 用來設置public的緩存。狀態碼爲 304, 注意這裏是去公共的緩存區域取數據,如 cdn, 不是在瀏覽器本地區數據。
  • private: 在瀏覽器上的緩存。對應max-age
  • public: 如cnd, 你們均可以訪問。對應s-maxage
  • no-cache: 設置了這個屬性,不會像max-age同樣,若是沒有過時,那麼直接去緩存取數據,而是會先發起一次請求,這個時候會帶上 If-None-Match 或者 if-Modified-since 去服務端詢問緩存是否過時,若是沒有過時服務端返回304, 而後去緩存區取數據,否者返回200, 並返回新的內容。
  • no-store: 當設置了這個屬性,就不會使用緩存策略

Expires

緩存過時時間,比max-age的優先級低

Last-Modified/If-Modified-Since

前面兩個頭部,能夠解決在指定的時間內在緩存當中去取數據,可是當咱們的服務端將數據更改以後,客戶端並不知道。

服務端返回一個文件最後修改時間Last-Modified, 在請求的時候帶上If-Modified-Since,在服務端進行比對,若是客戶端傳過來的時間小於服務器上文件的最後修改時間,那麼就返回200,並將相應的最新內容和Last-Modified給返回。否者返回304,文件內容未被修改。

須要注意的是,當設置了Max-age的時候,仍然走緩存,只有當Max-age過時了以後,這兩個字段纔會起做用

Etag / If-None-Match

前面的 Last-Modified/If-Modified-Since,存在一個缺點,那就是當服務端Last-Modified修改以後,可能文件內容並無發生改變,這個時候,其實並無必要去從新返回內容。因此咱們可使用文件的hash值,只有文件的hash值發生改變以後,文件內容才發生改變。

一樣須要注意的是,只有在Max-age或者Expire失效以後,Etag / If-None-Match纔有效。到服務端進行比對,未改變返回304,改變了返回200

Etag / If-None-Match的優先級比Last-Modified / If-Modified-Since優先級高。

服務端性能優化

用服務端的運算能力,來減輕瀏覽器端的運算壓力。

咱們以React爲例來講: 當咱們訪問覺得用React寫的網站時,首先會下載咱們的代碼,可是因爲React是基於數據驅動的,因此它還要進行一步渲染的過程,會將咱們的JSX轉換成virtualdom, 而後再轉換成html代碼,這一過程是須要時間的。

解決方案在服務端將React代碼渲染成html以後再返回瀏覽器端

  • 構建層模板編譯
  • 數據無關的prerender方式
  • 服務端渲染