Gzip是一種流行的檔案壓縮演算法,現在的應用十分廣泛,尤其是在Linux平台。以下這篇文章主要跟大家介紹了關於HTTP傳輸中gzip壓縮的相關資料,文中介紹的非常詳細,需要的朋友可以參考借鑒,下面一起學習學習吧。
前言
網頁載入速度加快的好處不言而喻,除了節省流量,改善用戶的瀏覽體驗外,另一個潛在的好處是Gzip與搜尋引擎的抓取工具有著更好的關係。例如 Google就可以透過直接讀取gzip檔案來比普通手動抓取更快地檢索網頁。在Google網站管理員工具(Google Webmaster Tools)可以看到,sitemap.xml.gz 是直接作為Sitemap被提交的。
而這些好處不僅限於靜態內容,PHP動態頁面和其他動態產生的內容均可以透過使用Apache壓縮模組壓縮,加上其他的效能調整機制和對應的伺服器端快取規則,這可以大大提高網站的效能。因此,對於部署在Linux伺服器上的PHP程序,在伺服器支援的情況下,我們建議你開啟使用Gzip Web壓縮。下面來一起看看詳細的介紹吧。
為什麼要開啟gZip
#我們傳送郵件給某人時,我們在傳輸之前把自己的文件壓縮一下,接收方收到文件後再去解壓縮取得文件。這中操作對我們來說都已經司空見慣。我們壓縮檔案的目的就是為了把傳輸檔案的體積減小,加快傳輸速度。我們在http 傳輸中開啟gZip 的目的也是如此,但是一般文章介紹gZip 時候總是結合一些服務端配置(nginx)或者構建工具插件(webpack)來說,列出一大堆配置讓人看的雲裡霧裡,以至於到最後還沒搞懂為什麼用,怎麼用這些問題。
http 與gZip
我們下面去探討這些問題
gZip 檔案怎麼通訊
我們傳輸壓縮檔案給別人時候一般都帶著後綴名.rar, .zip之類,對方在拿到檔案後根據相應的後綴名選擇不同的解壓縮方式然後去解壓縮檔案。我們在 http 傳輸時候解壓縮檔案的這個角色的扮演者就是我們使用的瀏覽器,但是瀏覽器怎麼分辨這個檔案是什麼格式,該用什麼格式去解壓縮呢?
在http/1.0 協定中關於服務端發送的資料可以配置一個Content-Encoding 字段,這個字段用於說明資料的壓縮方法
Content-Encoding: gzip Content-Encoding: compress Content-Encoding: deflate
客戶端在接受到返回的數據後去檢查對應欄位的訊息,然後根據對應的格式去做對應的解碼。客戶端在請求時,可以用 Accept-Encoding 欄位說明自己接受哪些壓縮方法。
Accept-Encoding: gzip, deflate
我們可以在瀏覽器的控制台中看到請求的相關資訊
相容性
#提到瀏覽器作為一個前端就不由自主的會想一個問題,會不會有瀏覽器不支援。 HTTP/1.0 是1996年5月發布的。好消息是基本上不用考慮相容性的問題,幾乎所有瀏覽器都支援它。值得一提的是 ie6的早起版本中存在一個會破壞 gZip的錯誤,後面 ie6本身在 WinXP SP2 中修復了這個問題,而且用這個版本的用戶數量也很少。
誰去壓縮檔案
這件事看起來似乎只能服務端來做,我們在網路上看到最多的也是諸如nginx 開啟gZip 設定之類的文章,但是現在前端流行spa 應用, 用react, vue 之類的框架時候總伴隨這套自己的腳手架,一般用webpack 作為打包工具,其中可以配置插件如compression-webpack-plugin 可以讓我們把生成文件進行gZip 等壓縮並產生對應的壓縮文件,而我們應用在架構時候有可能也會在服務區和前端文件中放置一層node 應用來進行介面鑑權和文件轉送。 nodejs中我們熟悉的express 框架中也有一個compression 中間件,可以開啟gZip,一時間看的人眼花繚亂,到底該用誰怎麼用呢?
服務端回應請求時候壓縮
其实 nginx 压缩和 node 框架中用中间件去压缩都是一样的,当我们点击网页发送一个请求时候,我们的服务端会找到对应的文件,然后对文件进行压缩返回压缩后的内容【当然可以利用缓存减少压缩次数】,并配置好我们上面提到的 Content-Encoding 信息。对于一些应用在构架时候并没有上游代理层,比如服务端就一层 node 就可以直接用自己本身的压缩插件对文件进行压缩,如果上游配有有 nginx 转发处理层,最好交给 nginx 来处理这些,因为它们有专门为此构建的内容,可以更好的利用缓存并减小开销(很多使用c语言编写的)。
我们看一些 nginx 中开启 gZip 压缩的一部分配置
# 开启gzip gzip on; # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩 gzip_min_length 1k; # gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明 gzip_comp_level 2; # 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
应用构建时候压缩
既然服务端都可以做了为什么 webpack 在打包前端应用时候还有这样一个压缩插件呢,我们可以在上面 nginx 配置中看到 gzip_comp_level 2 这个配置项,上面也有注释写道 1-10 数字越大压缩效果越好,但是会耗费更多的CPU和时间,我们压缩文件除了减少文件体积大小外,也是为了减少传输时间,如果我们把压缩等级配置的很高,每次请求服务端都要压缩很久才回返回信息回来,不仅服务器开销会增大很多,请求方也会等的不耐烦。但是现在的 spa 应用既然文件都是打包生成的,那如果我们在打包时候就直接生成高压缩等级的文件,作为静态资源放在服务器上,接收到请求后直接把压缩的文件内容返回回去会怎么样呢?
webpack 的 compression-webpack-plugin 就是做这个事情的,配置起来也很简单只需要在装置中加入对应插件,简单配置如下
const CompressionWebpackPlugin = require('compression-webpack-plugin'); webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp('\\.(js|css)$'), threshold: 10240, minRatio: 0.8 }) )
webpack 打包完成后生成打包文件外还会额外生成 .gz 后缀的压缩文件
那么这个插件的压缩等级是多少呢,我们可以在源码中看到默认的 level 是 9
... const zlib = require('zlib'); this.options.algorithm = zlib[this.options.algorithm]; ... this.options.compressionOptions = { level: options.level || 9, flush: options.flush ... }
可以看到压缩使用的是 zlib 库,而 zlib 分级来说,默认是 6 ,最高的级别就是9 Best compression (also zlib.Z_BEST_COMPRESSION),因为我们只有在上线项目时候才回去打包构建一次,所以我们在构建时候使用最高级的压缩方式压缩多耗费一些时间对我们来说根本没任何损耗,而我们在服务器上也不用再去压缩文件,只需要找到相应已经压缩过的文件直接返回就可以了。
服务端怎么找到这些文件
在应用层面解决这个问题还是比较简单的,比如上述压缩文件会产生index.css, index.js的压缩文件,在服务端简单处理可以判断这两个请求然后给予相对应的压缩文件。以 node 的 express 为例
... app.get(['/index.js','/index.css'], function (req, res, next) { req.url = req.url + '.gz' res.set('Content-Encoding', 'gzip') res.setHeader("Content-Type", generateType(req.path)) // 这里要根据请求文件设置content-type next() })
上面我们可以给请求返回 gZip 压缩后的数据了,当然上面的局限性太强也不可取,但是对于处理这个方面需求也已经有很多库存在,express 有 express-static-gzip 插件 koa 的 koa-static 则默认自带对 gZip 文件的检测,基本原理就是对请求先检测 .gz后缀的文件是否存在,再去根据结果返回不同的内容。
哪些文件可以被 gZip 压缩
gZip 可以压缩所有的文件,但是这不代表我们要对所有文件进行压缩,我们写的代码(css,js)之类的文件会有很好的压缩效果,但是图片之类文件则不会被 gzip 压缩太多,因为它们已经内置了一些压缩,一些文件(比如一些已经被压缩的像.zip文件那种)再去压缩可能会让生成的文件体积更大一些。当然已经很小的文件也没有去压缩的必要了。
实践
能开启 gZip 肯定是要开启的,具体使用在请求时候实时压缩还是在构建时候去生成压缩文件,就要看自己具体业务情况。
参考资料
How are zlib, gzip and zip related? What do they have in common and how are they different?
webpack gzip vs express gzip
What is gZip compression?
HTTP 协议
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
#以上是在HTTP中gzip壓縮問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!