gzip在web中的應用1

初識gzip

在使用webpack打包前端文件時,在一些文章中無心中看到過使用gzip壓縮技術,達到優化打包文件大小的效果。簡單配置操做以後,發現壓縮後的gzip文件,壓縮效果很好,至少可壓縮一半大小!驚訝之餘同時也有不少疑問,好比:css

  • gzip壓縮技術,如何用到已有的web項目中呢?
  • 後來又在其它地方看到nginx也能夠作gzip,那麼webpack和nginx的gzip有什麼關係嗎?
  • 這麼好的工具,爲何之前所經歷的項目中並無接觸到呢?
  • 是否是這個技術有什麼坑?
    帶着不少問題,開始查資料,作demo,一點一點了解它,慢慢的揭開它的真面目。

gzip和文件壓縮

Gzip是若干種文件壓縮程序的簡稱,「GNU計劃」 的實現,使用c語言實現。gzip的基礎是DEFLATE,DEFLATE是LZ77與哈夫曼編碼的一個組合體。初始版本於1992年10月31日,25年前發佈。 可見,gzip本來是在Unix-like操做系統上用來作數據壓縮的一種工具。html

gzip和http協議

HTTP壓縮是一種內置到網頁服務器和網頁客戶端中以改進傳輸速度和帶寬利用率的方式,最多見的壓縮方案包括gzip和Deflate。具體壓縮算法還有其它類型,這裏不作展開。可見gzip只是http壓縮方案中的其中一種,其完整流程須要客戶端和服務端同時支持。
那麼服務端和客戶端分別如何支持gzip的呢?前端

客戶端vue

  • 支持http壓縮的客戶端在發送請求的header裏配置 Accept-Encoding字段,用於說明本身可以理解的內容編碼方式。在接收到返回的數據後去檢查服務端響應頭,而後根據對應的格式去作相應的解碼,目前主流的瀏覽器,Chrome,firefox,IE等都支持該協議。
  • 不支持http壓縮的客戶端在發送請求的header裏配置不會添加Accept-Encoding字段。

服務端
服務端接收到客戶端請求頭Accept-Encoding字段後,端會選擇其中一種壓縮方案進行壓縮,使用並在響應報文首部 Content-Encoding 中表示消息主體進行了何種方式的內容編碼轉換,告知客戶端應該怎樣解碼才能獲取在 Content-Type 中標示的媒體類型內容。常見的服務器如Apache,Nginx,IIS都支持gzip。java

HTTP協議gzip壓縮的過程

  1. 客戶端發送Http request 給Web服務器, 兼容壓縮方案的瀏覽器會在http請求頭中帶上有Accept-Encoding: gzip。(告訴服務器, 客戶端支持gzip壓縮)
  2. 服務器對須要返回的文件進行Gzip壓縮,或者查找靜態資源是否存在已經壓縮好的gzip壓縮文件。(服務端想辦法生成或找到原始文件對應的gzip壓縮文件)
  3. 服務端將gzip文件發送給客戶端,而且設置相應header中除了包含有Content-Type,Content-Length等字段,還須要添加Content-Encoding:gzip用於說明壓縮文件的編碼方式。(服務端返回gzip文件並告訴客戶端壓縮方式爲gzip)
  4. 客戶端接到Response後,根據Content-Encoding:gzip來對Response 進行解碼。 獲取到原始response後, 而後顯示出網頁。(客戶端對gzip文件解碼)

誰來作壓縮?

服務端

  • 若是服務是部署在nginx上,可使用nginx 開啓 gZip 配置便可完成文件壓縮。
  • 若是服務是獨立部署,沒有部署在nginx等服務器上。好比常見的用於進行接口鑑權和文件轉發的node服務,須要在服務端實現gzip功能。具體如何實現,本人目前尚未實踐,我的猜測應該是尋找可用當前服務器語言對應的現成工具實現,若是沒有現成工具,則須要服務端自行完成。

客戶端

如今前端流行 spa 應用, 用 react, vue 之類的框架,通常配備 webpack 做爲打包工具,webpack有個插件 compression-webpack-plugin 能夠對打包文件進行 gZip 等壓縮並生成對應的壓縮文件。node

我的2點想法

  1. 若是服務端作壓縮,儘可能使用ngnix作
    服務端實現gzip壓縮的過程是相似的。 服務端收到客戶端請求後,先會找到對應的文件, 而後對文件進行壓縮,並配置好Content-Encoding 信息,返回壓縮後的內容,
  • 若是應用沒有上游代理層nginx等,好比服務端就一層 node 就能夠直接用本身自己的壓縮插件對文件進行壓縮。
  • 若是上游配有 nginx 轉發處理層,最好交給 nginx 來處理這些,nginx自己就自帶gzip壓縮功能,畢竟專業的事交給專業的工具作更爲放心。
  1. 提早預壓縮
    在服務端作gzip壓縮,壓縮發送在請求過程當中,須要耗費更多的CPU和時間,固然相似nginx的壓縮可能不必定每次都須要壓縮(待調研),但至少第一次壓縮是須要的。
    預壓縮就是提早把靜態文件進行gzip壓縮,當請求來的時候,直接讀走。這樣服務器就沒了壓縮消耗,而瀏覽器的解壓縮性能相比網絡IO,影響不大。
    有一種預壓縮方案能夠是使用客戶端webpack作gzip壓縮,而後開啓nginx的gzip_static選項(若是服務端不是nginx,實現方案待調研)
    因爲只有在上線項目時纔打包構建一次,即便在構建時使用最高級的壓縮方式壓縮,多耗費一些打包時間根本沒任何損耗,這樣服務器也不用再去壓縮文件,只須要找到相應已經壓縮過的文件直接返回就能夠了。

總結
能開啓 gZip 確定是要開啓的,具體使用在請求時候實時壓縮仍是在構建時候去生成壓縮文件,就要看本身具體業務狀況。python

大廠在用嗎?

瞭解大廠們是否在使用,是爲了知道做爲小白的我可否放心使用這項技術的參考之一。
在我寫這篇文章時,默默查看了下BAT首頁,京東,考拉...都用了gzip壓縮,這說明這個技術目前已經普及了。react

以淘寶首頁爲例查看請求和相應header便可知道是否使用gzip壓縮。 webpack

taobao

瞭解了關於gzip的一些基礎問題以後,下面主要演示一些demo小例子,介紹如何在web中應用這項技術。nginx

nginx作壓縮應用gzip

若是服務器是部署在nginx,則能夠經過修改nginx的配置文件實如今nginx中實現gzip壓縮,步驟以下:

1.準備好待測試的靜態頁面

寫一個簡單的靜態頁面,引入vue.js和element-ui.js(用來查看是否有gzip效果)

static
打開nginx的配置文件,將nginx的root目錄指向這個靜態頁面所在的目錄。
root

2.啓動gzip配置

在server下打開gzip開關

nginx-gzip-on

3.重啓nginx服務

配置好以後,重載nginx配置便可(若是重載不成功,則重啓)
這裏的命令是mac系統上的nginx重啓命令。
sudo brew services reload nginx
sudo brew services restart nginx

效果:文件大小對比

對比沒有開啓gzip和開啓了gzip的文件大小。 能夠看到壓縮後的html,js,css文件比原始文件小不少,可見這個壓縮效果至關可觀的。

ret1

webpack作壓縮應用gzip

在webpack中主要是經過插件compression-webpack-plugin實現本地打包時的gzip壓縮,具體步驟以下:

1.準備好待測試的使用webpack打包的工程

略,讀者自行實現。

2.安裝配置compression-webpack-plugin

安裝插件
npm install compression-webpack-plugin --save-dev

3.修改webpack配置

在webpack配置文件中添加下面幾行配置:
const CompressionPlugin = require('compression-webpack-plugin'); ...
plugins: [new CompressionPlugin() ]

4.執行本地打包

  • 沒有使用compression-webpack-plugin的打包結果: 只有2個文件,build.js是958878
    local1
  • 使用了compression-webpack-plugin的打包結果:生成了4個文件,build.js是958878,build.js.gz是231189
    local2

5. 服務端配合測試

使用webpack打包時壓縮,須要服務端的配合才能生效的。下面以nginx做爲服務端爲例,測試以下。
首先讓nginx的root指向本地打包的index.html頁面;
而後關閉或開啓nginx的gzip_static配置對比效果;

  • 關閉gzip_static,重載nginx配置效果以下

  • 開啓gzip_static,重載nginx配置

總結和展望

通過上面的分析,再一一回到開頭提出的問題

  • gzip壓縮以後,我怎麼用到項目中呢?
    答:若是是nginx,須要開啓gzip_static配置便可,若是是其它服務器還須要其它服務器自行實現。
  • 後來又在其它地方看到nginx也能夠作gzip,那麼webpack和nginx的gzip有什麼關係嗎?
    答:webpack是一個打包工具,能夠打包js,同時經過插件對js文件進行gzip壓縮,而後能夠將這些文件所有丟給服務端,若是服務部署在nginx則能夠作些配置,對.gz文件進行查找,若是找到了則返回.gz給客戶端,來代替原始js給客戶端,以減小網絡傳輸中的文件大小,若是沒找到,也能夠配置nginx本身作壓縮,而後返回給客戶端。所以能夠知道nginx能夠單獨實現gzip,可是webpack須要服務端配合才能實現。
  • 這麼好的工具,爲何之前所經歷的項目中並無接觸到呢?
    答:不知道爲何沒用...可是瞭解了這些以後,在之後的項目中,會打算積極的使用gzip壓縮的。
  • 這個技術有什麼坑嗎?
    答:目前爲止我還不知道...

在這個過程當中,又出現了幾個新的問題,好比

  • 若是是服務不是部署在nginx端,好比部署在node,python,rails,java中的話,如何配合webpack實現gzip呢?
  • 若是啓用nginx本身的gzip壓縮,對於每次請求,nginx每次都是實時計算壓縮文件的嗎?我的直覺應該不是吧?若是不是,那麼使用nginx直接壓縮是否是也很方便呢?nginx自身可否實現預壓縮呢?
  • 除了gzip壓縮,其它壓縮好比facebook使用的Brotli,是否是壓縮效果更好呢?

到此,依然有不少問題須要繼續瞭解...

相關文章
相關標籤/搜索