怎么把網(wǎng)站的標(biāo)題做的炫酷互聯(lián)網(wǎng)營(yíng)銷(xiāo)師培訓(xùn)教材
一、gZip簡(jiǎn)單介紹
1.1 什么是gzip
gzip是GNUzip的縮寫(xiě),最早用于UNIX系統(tǒng)的文件壓縮。HTTP協(xié)議上的gzip編碼是一種用來(lái)改進(jìn)web應(yīng)用程序性能的技術(shù),web服務(wù)器和客戶(hù)端(瀏覽器)必須共同支持gzip。目前主流的瀏覽器,Chrome,firefox,IE等都支持該協(xié)議。常見(jiàn)的服務(wù)器如Apache,Nginx,IIS同樣支持gzip。
gzip壓縮比率在3到10倍左右,可以大大節(jié)省服務(wù)器的網(wǎng)絡(luò)帶寬。而在實(shí)際應(yīng)用中,并不是對(duì)所有文件進(jìn)行壓縮,通常只是壓縮靜態(tài)文件。
1.1.1 gzip工作原理圖
1.1.2 gzip的工作過(guò)程
瀏覽器請(qǐng)求url,并在request header中設(shè)置屬性accept-encoding:gzip。表明瀏覽器支持gzip。
服務(wù)器收到瀏覽器發(fā)送的請(qǐng)求之后,判斷瀏覽器是否支持gzip,如果支持gzip,則向?yàn)g覽器傳送壓縮過(guò)的內(nèi)容,不支持則向?yàn)g覽器發(fā)送未經(jīng)壓縮的內(nèi)容。一般情況下,瀏覽器和服務(wù)器都支持gzip,response headers返回包含content-encoding:gzip。
瀏覽器接收到服務(wù)器的響應(yīng)之后判斷內(nèi)容是否被壓縮,如果被壓縮則解壓縮顯示頁(yè)面內(nèi)容。
1.2 為什么要開(kāi)啟gZip
我們給某人發(fā)送郵件時(shí),我們?cè)趥鬏斨鞍炎约旱奈募嚎s一下,接收方收到文件后再去解壓獲取文件。這中操作對(duì)于我們來(lái)說(shuō)都已經(jīng)司空見(jiàn)慣。我們壓縮文件的目的就是為了把傳輸文件的體積減小,加快傳輸速度。我們?cè)?http 傳輸中開(kāi)啟 gZip 的目的也是如此,但是一般文章介紹 gZip 時(shí)候總是結(jié)合一些服務(wù)端配置(nginx)或者構(gòu)建工具插件(webpack)來(lái)說(shuō),列出一大堆配置讓人看的云里霧里,以至于到最后還沒(méi)搞懂 為什么用,怎么用 這些問(wèn)題。
1.3 gZip 文件怎么通訊
我們傳輸壓縮文件給別人時(shí)候一般都帶著后綴名 .rar, .zip之類(lèi),對(duì)方在拿到文件后根據(jù)相應(yīng)的后綴名選擇不同的解壓方式然后去解壓文件。我們?cè)?http 傳輸時(shí)候解壓文件的這個(gè)角色的扮演者就是我們使用的瀏覽器,但是瀏覽器怎么分辨這個(gè)文件是什么格式,應(yīng)該用什么格式去解壓呢?
在 http/1.0 協(xié)議中關(guān)于服務(wù)端發(fā)送的數(shù)據(jù)可以配置一個(gè) Content-Encoding 字段,這個(gè)字段用于說(shuō)明數(shù)據(jù)的壓縮方法
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客戶(hù)端在接受到返回的數(shù)據(jù)后去檢查對(duì)應(yīng)字段的信息,然后根據(jù)對(duì)應(yīng)的格式去做相應(yīng)的解碼??蛻?hù)端在請(qǐng)求時(shí),可以用 Accept-Encoding 字段說(shuō)明自己接受哪些壓縮方法。
Accept-Encoding: gzip, deflate
我們?cè)跒g覽器的控制臺(tái)中可以看到請(qǐng)求的相關(guān)信息
兼容性
提到瀏覽器作為一個(gè)前端就不由自主的會(huì)想一個(gè)問(wèn)題,會(huì)不會(huì)有瀏覽器不支持呢。HTTP/1.0 是1996年5月發(fā)布的。好消息是基本不用考慮兼容性的問(wèn)題,幾乎所有瀏覽器都支持它。值得一提的是 ie6的早起版本中存在一個(gè)會(huì)破壞 gZip的錯(cuò)誤,后面 ie6本身在 WinXP SP2 中修復(fù)了這個(gè)問(wèn)題,而且用這個(gè)版本的用戶(hù)數(shù)量也很少。
1.4 誰(shuí)去壓縮文件
這件事看起來(lái)貌似只能服務(wù)端來(lái)做,我們?cè)诰W(wǎng)上看到最多的也是諸如 nginx 開(kāi)啟 gZip 配置之類(lèi)的文章,但是現(xiàn)在前端流行 spa 應(yīng)用, 用 react, vue 之類(lèi)的框架時(shí)候總伴隨這一套自己的腳手架,一般用 webpack 作為打包工具,其中可以配置插件 如compression-webpack-plugin 可以讓我們把生成文件進(jìn)行 gZip 等壓縮并生成對(duì)應(yīng)的壓縮文件,而我們應(yīng)用在構(gòu)架時(shí)候有可能也會(huì)在服務(wù)區(qū)和前端文件中放置一層 node 應(yīng)用來(lái)進(jìn)行接口鑒權(quán)和文件轉(zhuǎn)發(fā)。nodejs中我們熟悉的express 框架中也有一個(gè)compression 中間件,可以開(kāi)啟gZip,一時(shí)間看的人眼花繚亂,到底應(yīng)該用誰(shuí)怎么用呢?
- 服務(wù)端響應(yīng)請(qǐng)求時(shí)候壓縮
其實(shí) nginx 壓縮和 node 框架中用中間件去壓縮都是一樣的,當(dāng)我們點(diǎn)擊網(wǎng)頁(yè)發(fā)送一個(gè)請(qǐng)求時(shí)候,我們的服務(wù)端會(huì)找到對(duì)應(yīng)的文件,然后對(duì)文件進(jìn)行壓縮返回壓縮后的內(nèi)容【當(dāng)然可以利用緩存減少壓縮次數(shù)】,并配置好我們上面提到的 Content-Encoding 信息。對(duì)于一些應(yīng)用在構(gòu)架時(shí)候并沒(méi)有上游代理層,比如服務(wù)端就一層 node 就可以直接用自己本身的壓縮插件對(duì)文件進(jìn)行壓縮,如果上游配有有 nginx 轉(zhuǎn)發(fā)處理層,最好交給 nginx 來(lái)處理這些,因?yàn)樗鼈冇袑?zhuān)門(mén)為此構(gòu)建的內(nèi)容,可以更好的利用緩存并減小開(kāi)銷(xiāo)(很多使用c語(yǔ)言編寫(xiě)的)。
我們看一些 nginx 中開(kāi)啟 gZip 壓縮的一部分配置
# 開(kāi)啟gzip
gzip on;
# 啟用gzip壓縮的最小文件,小于設(shè)置值的文件將不會(huì)壓縮
gzip_min_length 1k;
# gzip 壓縮級(jí)別,1-10,數(shù)字越大壓縮的越好,也越占用CPU時(shí)間,后面會(huì)有詳細(xì)說(shuō)明
gzip_comp_level 2;
# 進(jìn)行壓縮的文件類(lèi)型。javascript有多種形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
- 應(yīng)用構(gòu)建時(shí)候壓縮
既然服務(wù)端都可以做了為什么 webpack 在打包前端應(yīng)用時(shí)候還有這樣一個(gè)壓縮插件呢,我們可以在上面 nginx 配置中看到 gzip_comp_level 2 這個(gè)配置項(xiàng),上面也有注釋寫(xiě)道 1-10 數(shù)字越大壓縮效果越好,但是會(huì)耗費(fèi)更多的CPU和時(shí)間,我們壓縮文件除了減少文件體積大小外,也是為了減少傳輸時(shí)間,如果我們把壓縮等級(jí)配置的很高,每次請(qǐng)求服務(wù)端都要壓縮很久才回返回信息回來(lái),不僅服務(wù)器開(kāi)銷(xiāo)會(huì)增大很多,請(qǐng)求方也會(huì)等的不耐煩。但是現(xiàn)在的 spa 應(yīng)用既然文件都是打包生成的,那如果我們?cè)诖虬鼤r(shí)候就直接生成高壓縮等級(jí)的文件,作為靜態(tài)資源放在服務(wù)器上,接收到請(qǐng)求后直接把壓縮的文件內(nèi)容返回回去會(huì)怎么樣呢?
webpack 的 compression-webpack-plugin 就是做這個(gè)事情的,配置起來(lái)也很簡(jiǎn)單只需要在裝置中加入對(duì)應(yīng)插件,簡(jiǎn)單配置如下
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 打包完成后生成打包文件外還會(huì)額外生成 .gz 后綴的壓縮文件
那么這個(gè)插件的壓縮等級(jí)是多少呢,我們可以在源碼中看到默認(rèn)的 level 是 9
...
const zlib = require('zlib');
this.options.algorithm = zlib[this.options.algorithm];
...
this.options.compressionOptions = {
level: options.level || 9,
flush: options.flush
...
}
可以看到壓縮使用的是 zlib 庫(kù),而 zlib 分級(jí)來(lái)說(shuō),默認(rèn)是 6 ,最高的級(jí)別就是9 Best compression (also zlib.Z_BEST_COMPRESSION),因?yàn)槲覀冎挥性谏暇€(xiàn)項(xiàng)目時(shí)候才回去打包構(gòu)建一次,所以我們?cè)跇?gòu)建時(shí)候使用最高級(jí)的壓縮方式壓縮多耗費(fèi)一些時(shí)間對(duì)我們來(lái)說(shuō)根本沒(méi)任何損耗,而我們?cè)诜?wù)器上也不用再去壓縮文件,只需要找到相應(yīng)已經(jīng)壓縮過(guò)的文件直接返回就可以了。
3. 服務(wù)端怎么找到這些文件
在應(yīng)用層面解決這個(gè)問(wèn)題還是比較簡(jiǎn)單的,比如上述壓縮文件會(huì)產(chǎn)生index.css, index.js的壓縮文件,在服務(wù)端簡(jiǎn)單處理可以判斷這兩個(gè)請(qǐng)求然后給予相對(duì)應(yīng)的壓縮文件。以 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)) // 這里要根據(jù)請(qǐng)求文件設(shè)置content-type
next()
})
上面我們可以給請(qǐng)求返回 gZip 壓縮后的數(shù)據(jù)了,當(dāng)然上面的局限性太強(qiáng)也不可取,但是對(duì)于處理這個(gè)方面需求也已經(jīng)有很多庫(kù)存在,express 有 express-static-gzip 插件 koa 的 koa-static 則默認(rèn)自帶對(duì) gZip 文件的檢測(cè),基本原理就是對(duì)請(qǐng)求先檢測(cè) .gz后綴的文件是否存在,再去根據(jù)結(jié)果返回不同的內(nèi)容。
1.5 哪些文件可以被 gZip 壓縮
gZip 可以壓縮所有的文件,但是這不代表我們要對(duì)所有文件進(jìn)行壓縮,我們寫(xiě)的代碼(css,js)之類(lèi)的文件會(huì)有很好的壓縮效果,但是圖片之類(lèi)文件則不會(huì)被 gzip 壓縮太多,因?yàn)樗鼈円呀?jīng)內(nèi)置了一些壓縮,一些文件(比如一些已經(jīng)被壓縮的像.zip文件那種)再去壓縮可能會(huì)讓生成的文件體積更大一些。當(dāng)然已經(jīng)很小的文件也沒(méi)有去壓縮的必要了。
能開(kāi)啟 gZip 肯定是要開(kāi)啟的,具體使用在請(qǐng)求時(shí)候?qū)崟r(shí)壓縮還是在構(gòu)建時(shí)候去生成壓縮文件,就要看自己具體業(yè)務(wù)情況。
二、優(yōu)化思路
zip 文件由哪端生成?
這個(gè)是一個(gè)問(wèn)題,網(wǎng)上大部分教程會(huì)告訴你,在服務(wù)端配置nginx, 然后 xxx 一波操作猛如虎。 但是對(duì)于新手來(lái)說(shuō),這樣真的好嗎?不告訴人家原理,是不行的。
2.1 服務(wù)端生成
zip 文件可以服務(wù)端生成,例如:
2.1.1 nginx
nginx 有一個(gè)模塊是 gzip 模塊,然后你只要開(kāi)啟了,nginx就會(huì)幫你來(lái)把數(shù)據(jù)(靜態(tài)資源 和 接口數(shù)據(jù))進(jìn)行壓縮,然后傳入到客戶(hù)端,客戶(hù)端來(lái)解壓,然后在進(jìn)行代碼的讀取,其實(shí)這一步就是節(jié)約帶寬,減少傳輸?shù)拇a包的數(shù)量。從而節(jié)約傳輸時(shí)間。然后網(wǎng)站就能很快打開(kāi)了。
2.1.2 node
node也有相關(guān)于 compression 的庫(kù),然后配置一些選項(xiàng),來(lái)選擇對(duì)數(shù)據(jù)(資源和接口數(shù)據(jù))的壓縮,這個(gè)是同一個(gè)道理,就是服務(wù)端來(lái)進(jìn)行壓縮嘛,然后在傳輸。
其他的服務(wù)也有相關(guān)的庫(kù),怎么使用要看對(duì)于的語(yǔ)言了,這里就不展開(kāi)。
2.2 客戶(hù)端生成
既然 服務(wù)端可以生成gzip文件, 那些構(gòu)建工具 webpack, rollup, 等為啥也要寫(xiě)一些壓縮的包? 而且會(huì)發(fā)現(xiàn)包好像周下載量還停高的。
例如:
為啥要客戶(hù)端生成呢?
問(wèn)得好, 我們知道服務(wù)端生成是不是每一次請(qǐng)求都要去請(qǐng)求服務(wù)器,然后服務(wù)器來(lái)生成壓縮包。服務(wù)器每一次生成壓縮包是不是會(huì)不會(huì)浪費(fèi)服務(wù)端的性能哇!, 如果客戶(hù)端生成,服務(wù)端先判斷是否存在的后綴名為zip的文件,直接去拿,不存在再壓縮,這樣是不是把服務(wù)器每一次都要壓縮的事情,交給客戶(hù)端了呢? 雖然客戶(hù)端打包進(jìn)行代碼壓縮會(huì)很慢。 但是我們打包只是發(fā)布代碼的時(shí)候打一次包,而服務(wù)器是要面對(duì)成千上萬(wàn)的人來(lái)訪(fǎng)問(wèn)等。 說(shuō)到這里大家應(yīng)該明白了吧。
三、優(yōu)化實(shí)戰(zhàn)
服務(wù)器主要使用windows服務(wù)器,配合IIS使用,nginx也會(huì)簡(jiǎn)單介紹下配置。
3.1 服務(wù)端壓縮
對(duì)于服務(wù)端來(lái)進(jìn)行壓縮,客戶(hù)端啥也不用做,只需要把打好的包放入對(duì)應(yīng)的目錄下面,然后在訪(fǎng)問(wèn)的時(shí)候 nginx 自動(dòng)進(jìn)行壓縮傳給客戶(hù)端進(jìn)行解析等。
3.1.1 nginx配置
使用HttpGzip(這個(gè)模塊支持在線(xiàn)實(shí)時(shí)壓縮輸出數(shù)據(jù)流)模塊.
下面這一段命令的作用域是 : http, server, location, 意思是在 http, server, location 這三個(gè)地方加入到哪個(gè)地方都行,為了不影響其他的,個(gè)人建議加到 location模塊,這樣其他的就不會(huì)影響了。
gzip on;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php;
效果
主要加載的是這個(gè)應(yīng)用
3.2 客戶(hù)端壓縮
在客戶(hù)的壓縮工具也有很多,這里我就介紹webpack 和 vite 客戶(hù)端怎么進(jìn)行壓縮然后部署。
3.2.1 webpack
1. 使用Gzip
用npm安裝gzip插件
//安裝低版本
npm install --save-dev compression-webpack-plugin
在vue.config.js中配置,引入插件
//引入gzip壓縮插件
const CompressionPlugin = require('compression-webpack-plugin')
使用插件,在vue.config.js文件中configureWebpack的plugins中添加配置new CompressionPlugin(…)或如下在最后加入
configureWebpack:config => {if(process.env.NODE_ENV === "production"){return {plugins:[new CompressionPlugin({algorithm: 'gzip', // 使用gzip壓縮test: /\.js$|\.html$|\.css$/, // 匹配文件名filename: '[path][base].gz[query]', // 壓縮后的文件名(保持原文件名,后綴加.gz)minRatio: 0.8,threshold: 10240, // 對(duì)超過(guò)10k的數(shù)據(jù)壓縮,一般都會(huì)選擇大于1字節(jié)的進(jìn)行壓縮,小于1字節(jié)可能壓縮后反而體積更大了deleteOriginalAssets: false, // 是否刪除未壓縮的源文件,謹(jǐn)慎設(shè)置,如果希望提供非gzip的資源,可不設(shè)置或者設(shè)置為false(比如刪除打包后的gz后還可以加載到原始資源文件)}),]}}},
2. 打包發(fā)布
插件導(dǎo)入后,npm run build打包,在dist文件夾中查看,可以看到.gz格式的文件
壓縮前后文件大小對(duì)比![
把打包好的靜態(tài)文件部署在服務(wù)器,使用鏈接訪(fǎng)問(wèn)網(wǎng)頁(yè),發(fā)現(xiàn)加載時(shí)間需要十幾秒
dist文件在IIS發(fā)布后,選擇壓縮
開(kāi)啟靜態(tài)內(nèi)容壓縮(不建議選中壓縮應(yīng)用程序文件,但一定要選上壓縮靜態(tài)文件,不然就等于沒(méi)有壓縮,達(dá)不到負(fù)載均衡了。)
另一篇文章看見(jiàn)的開(kāi)啟操作,實(shí)際上我沒(méi)做下方引用部分的內(nèi)容:
- 然后選中我那個(gè)站下面那個(gè)服務(wù)器擴(kuò)展,新建一個(gè)服務(wù)器擴(kuò)展,名字為GZIP,下面的添加文件路徑為:c:\windows\system32\inetsrv\gzip.dll,然后啟用這個(gè)擴(kuò)展。
- 我們要修改配置文件,在配置文件之前要停止IIS服務(wù),(提醒大家一定要先關(guān)閉IIS服務(wù))打開(kāi)C:\Windows\System32\inetsrv\MetaBase.xml,這個(gè)文件很大,找到下面一段信息
<IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/gzip"<br> <br><br>HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"<br> <br><br>HcCreateFlags="1"<br><br><br> HcDoDynamicCompression="TRUE"<br> <br><br>HcDoOnDemandCompression="TRUE"<br><br><br> HcDoStaticCompression="TRUE"<br> <br><br>HcDynamicCompressionLevel="6"<br> <br><br>HcFileExtensions="htm<br><br>html<br><br>txtjscss"<br><br><br> HcOnDemandCompLevel="10"<br> <br><br>HcPriority="1"<br><br><br> HcScriptFileExtensions="asp<br><br>dll<br><br>exe"<br><br>><br><br><br></IIsCompressionScheme><br><IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/deflate"<br> HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"<br> HcCreateFlags="0"<br> HcDoDynamicCompression="TRUE"<br> HcDoOnDemandCompression="TRUE"<br> HcDoStaticCompression="true"<br> HcDynamicCompressionLevel="9"<br> HcFileExtensions="htm<br> html<br> txt<br> js<br> css <br> swf<br> xml"<br> HcOnDemandCompLevel="9"<br> HcPriority="1"<br> HcScriptFileExtensions="asp <br> aspx<br> dll<br> exe"<br> ><br></IIsCompressionScheme><br><IIsCompressionScheme Location ="/LM/W3SVC/Filters/Compression/gzip"<br> HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"<br> HcCreateFlags="1"<br> HcDoDynamicCompression="TRUE"<br> HcDoOnDemandCompression="TRUE"<br> HcDoStaticCompression="true"<br> HcDynamicCompressionLevel="9"<br> HcFileExtensions="htm<br> html<br> txt<br> js<br> css <br> swf<br> xml"<br> HcOnDemandCompLevel="9"<br> HcPriority="1"<br> HcScriptFileExtensions="asp <br> aspx<br> dll<br> exe"<br> ><br></IIsCompressionScheme>
修改這個(gè)文件是要增加一些要進(jìn)行壓縮的文件后綴,其中 HcFileExtensions 是靜態(tài)文件的擴(kuò)展名,增加 js 和 css
等;HcScriptFileExtensions 為動(dòng)態(tài)文件的擴(kuò)展名,增加
aspx,HcDynamicCompressionLevel改成9,(0-10,6是性?xún)r(jià)比最高的一個(gè))。 重啟一下IIS服務(wù)
如果IIS里啟用動(dòng)態(tài)內(nèi)容壓縮是灰色的,則需要在服務(wù)器上安裝下:
在windows【服務(wù)管理】中,選擇【增加功能和角色】
,然后在服務(wù)器角色中,按下圖操作
安裝完成后,在IIS中看到的【啟用動(dòng)態(tài)內(nèi)容壓縮】不再為灰選狀態(tài),表示安裝成功。
此時(shí)訪(fǎng)問(wèn),可以看到瀏覽器,查看chunk.js的網(wǎng)絡(luò)請(qǐng)求的回應(yīng),發(fā)現(xiàn)已經(jīng)有了content-encoding的壓縮回應(yīng),為gzip格式
關(guān)于vue配置gZip的更詳細(xì)配置:https://segmentfault.com/a/1190000024497914
3.2.2 vite
本人項(xiàng)目是使用vite來(lái)進(jìn)行構(gòu)建的
這里也需要安裝一個(gè)插件, 一開(kāi)始我以為是 rollup-plugin-gzip 后面發(fā)現(xiàn)不對(duì),vite 自己做了一個(gè)插件出來(lái)。vite-plugin-compression 使用方式很簡(jiǎn)單
import viteCompression from 'vite-plugin-compression';
plugins: [viteCompression()],
效果如下:
nginx 配置
沒(méi)錯(cuò),這里nginx 也要配置, 配置啟動(dòng)gzip模塊, 然后優(yōu)先使用本地壓縮好的文件。
gzip_static on;
gzip_http_version 1.1;
gzip_proxied expired no-cache no-store private auth;
效果