使用node.js壓縮流優化http請求

前端性能優化一直是一個值得討論的話題,而節省每次HTTP請求的流量,則是優化的一個重要的點,好比javascript文件、圖片、樣式表等進行壓縮傳輸,不只使訪問速度更快,也能夠有效的節省站點的流量。javascript

HTTP的請求中帶有一個頭Content-Encoding來處理壓縮。前端

常見的壓縮模式:java

  • GZIP
  • Deflate

GZIP

GZIP最先由Jean-loup Gailly和Mark Adler建立,用於UNⅨ系統的文件壓縮。咱們在Linux中常常會用到後綴爲.gz的文件,它們就是GZIP格式的。現今已經成爲Internet 上使用很是廣泛的一種數據壓縮格式,或者說一種文件格式。node

Deflate

DEFLATE是同時使用了LZ77算法與哈夫曼編碼(Huffman Coding)的一個無損數據壓縮算法。 它最初是由Phil Katz爲他的PKZIP歸檔工具第二版所定義的,後來定義在RFC 1951規範中。算法

在node.js中使用壓縮流

node.js中已經爲咱們提供了壓縮的功能,它的核心功能在zlib包裏。瀏覽器

zlib模塊提供經過 Gzip 和 Deflate/Inflate 實現的壓縮功能。性能優化

使用方法

const zlib = require('zlib');
const fs = require('fs');
const path = require('path');

let file = path.join(__dirname, './1.txt');
zip(file);

function zip(file) {
  let gzip = zlib.createGzip(); //gzip是一個轉換流
  fs.createReadStream(file).pipe(gzip).pipe(fs.createWriteStream(file + '.gz'));
}

複製代碼

能夠看到用法很是簡單,使用createGzip能夠建立一個gzip壓縮流,它是一個Transform轉換流。首先使用待壓縮的目標文件建立一個可讀流,將它pipe到gzip壓縮流中,再pipe到一個可寫流中,便可完成壓縮。運行這段代碼能夠看到在模塊目錄下已經多了一個1.txt.gz的壓縮包。服務器

unzip(path.join(__dirname, './1.txt.gz'));
function unzip(file) {
  let gunzip = zlib.createGunzip(file);
  fs.createReadStream(file).pipe(gunzip).pipe(fs.createWriteStream(path.basename(file, '.gz')));
}
複製代碼

解壓縮一樣如此,使用解壓縮流便可。前端性能

使用壓縮優化http請求

瞭解了壓縮流的使用,怎麼樣才能配合http來優化用戶的請求呢?工具

http有一個字段,它描述了瀏覽器支持哪一種壓縮格式:

Accept-Encoding: gzip, deflate, br
複製代碼

響應頭

Content-Encoding: gzip
複製代碼

處理流程:

  1. 首先查看http請求頭Accept-Encoding都支持哪些壓縮格式
  2. 根據不一樣的壓縮格式將資源壓縮並輸出到瀏覽器
  3. 對不一樣的壓縮格式發送響應頭Content-Encoding

實例代碼:

const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const zlib = require('zlib');

let server = http.createServer((req, res) => {
  let {pathname} = url.parse(req.url, true);

  if (pathname === '/') {
    res.end('請訪問一個服務器上的文件 如http://localhost:3000/1.txt');
  }

  let file = path.join(__dirname, pathname);

  fs.stat(file, (err, stat) => {
    if (err) {
      res.end('訪問的文件不存在');
    } else {

      let acceptEncoding = req.headers['accept-encoding']; //取得瀏覽器的accept-encoding頭,詢問支持哪一種壓縮
      if (acceptEncoding.match(/\bgzip\b/)) { //瀏覽器支持gzip格式
        res.setHeader('Content-Encoding', 'gzip'); //告知瀏覽器發送的數據是gzip壓縮格式
        let gzip = zlib.createGzip();
        fs.createReadStream(file).pipe(gzip).pipe(res); //壓縮後輸出
      } else if (acceptEncoding.match(/\bdeflate\b/)) { //瀏覽器支持deflate格式
        let deflate = zlib.createDeflate();
        res.setHeader('Content-Encoding','deflate');
        fs.createReadStream(file).pipe(deflate).pipe(res); 壓縮後輸出
      } else {
        fs.createReadStream(file).pipe(res);
      }
    }
  });
});

server.listen(3000, () => {
  console.log('服務器已啓動在3000端口...')
});
複製代碼

重要代碼說明:

let acceptEncoding = req.headers['accept-encoding'];
複製代碼

取得瀏覽器的請求頭,查看支持哪些壓縮格式,由於某些老舊瀏覽器是不支持壓縮的,所以要針對不一樣的壓縮格式分別處理。

if (acceptEncoding.match(/\bgzip\b/)) {
複製代碼

使用正則來進行判斷,看看是否支持gzip壓縮

res.setHeader('Content-Encoding', 'gzip'); //告知瀏覽器發送的數據是gzip壓縮格式
複製代碼

使用setHeader來設置響應頭,告知瀏覽器此數據是經gzip壓縮的,這樣瀏覽器纔會正確處理,不然瀏覽器並不識別gzip數據。

deflate格式的邏輯徹底同樣,這樣就能夠作到http壓縮以節省流量的目的。

相關文章
相關標籤/搜索