使用 brotli 壓縮網路酬載

Michael DiBlasio
Michael DiBlasio

本程式碼研究室是壓縮及壓縮網路酬載程式碼研究室的延伸內容,且假設您已熟悉壓縮的基本概念。相較於 gzip 等其他壓縮演算法,本程式碼研究室將探討 Brotli 壓縮如何進一步降低壓縮率和應用程式整體大小。

應用程式螢幕截圖

測量

著手新增最佳化項目之前,最好先分析應用程式的目前狀態。

  1. 按一下「Remix to Edit」即可編輯專案。
  2. 如要預覽網站,請按下「View App」,然後按下「Fullscreen」全螢幕

在先前的壓縮及壓縮網路酬載程式碼研究室中,我們將 main.js 的大小從 225 KB 縮減為 61.6 KB。在本程式碼研究室中,您將探索 Brotli 壓縮如何進一步縮減這個套件大小。

Brotli 壓縮

Brotli 是較新的壓縮演算法,文字壓縮結果比 gzip 更好。根據 CertSimple,Britli 的效能具有:

  • JavaScript 比 gzip 小 14%
  • HTML 比 gzip 小 21%
  • CSS 比 gzip 小 17%

如要使用 Brotli,你的伺服器必須支援 HTTPS。大部分瀏覽器最新版本支援 Brotli。支援 Brotli 的瀏覽器會在 Accept-Encoding 標頭中加入 br

Accept-Encoding: gzip, deflate, br

您可以透過 Chrome 開發人員工具網路分頁 (Command+Option+ICtrl+Alt+I) 中的 Content-Encoding 欄位,判斷使用哪種壓縮演算法:

網路面板

啟用 Brotli

動態壓縮

動態壓縮牽涉到即時壓縮瀏覽器要求的資產。

優點

  • 您不需要建立與更新已儲存的資產壓縮版本。
  • 對於動態產生的網頁而言,即時壓縮效果尤佳。

缺點

  • 壓縮較高層級的檔案可以提高壓縮率,但所需時間會拉長。這可能會導致效能命中,因為使用者等待素材資源在伺服器送出之前先壓縮。

使用 Node/Express 動態壓縮

server.js 檔案負責設定託管應用程式的節點伺服器。

var express = require('express');

var app = express();

app.use(express.static('public'));

var listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

目前只會匯入 express,並使用 express.static 中介軟體在 public/directory 中載入所有靜態 HTML、JS 和 CSS 檔案 (而且這些檔案是由 webpack 與每個版本建立)。

為確保所有資產每次要求時都會使用 brotli 壓縮,可以使用 shrink-ray 模組。第一步,是將其新增為 package.json 中的 devDependency

"devDependencies": {
  //...
  "shrink-ray": "^0.1.3"
},

並匯入伺服器檔案 server.js

var express = require('express');
var shrinkRay = require('shrink-ray');

並在掛接 express.static 前將其新增為中介軟體:

//...
var app = express();

// compress all requests
app.use(shrinkRay());

app.use(express.static('public'));

現在,請重新載入應用程式,然後在「網路」面板中查看軟體包大小:

採用動態 Brotli 壓縮格式的軟體包大小

您現在可以在 Content-Encoding 標頭中看到 brotlibz 套用。main.bundle.js225 KB 縮減為 53.1 KB!相較於 gzip (61.6 KB),這個數量縮減約 14%。

靜態壓縮

靜態壓縮的原理是將資產壓縮並儲存。

優點

  • 再也不用擔心因為壓縮等級造成延遲的問題。因為現在可以直接擷取檔案,不需要進行任何即時壓縮。

缺點

  • 每個版本都需要壓縮資產。如果使用高壓縮率,建構時間可能會大幅增加。

使用 Node/Express 和 webpack 進行靜態壓縮

由於靜態壓縮需要預先壓縮檔案,因此您可以在建構步驟中修改 webpack 設定來壓縮資產。這時可以使用 brotli-webpack-plugin

第一步,是將其新增為 package.json 中的 devDependency

"devDependencies": {
  //...
 "brotli-webpack-plugin": "^1.1.0"
},

如同任何其他 webpack 外掛程式,請將其匯入設定檔 webpack.config.js

var path = require("path");

//...
var BrotliPlugin = require('brotli-webpack-plugin');

並在 Plugins 陣列中加入這個程式碼:

module.exports = {
  // ...
  plugins: [
    // ...
    new BrotliPlugin({
      asset: '[file].br',
      test: /\.(js)$/
    })
  ]
},

外掛程式陣列使用下列引數:

  • asset:目標資產名稱。
  • 系統會將 [file] 替換為原始素材資源檔案名稱。
  • test:系統會處理所有與這個規則運算式相符的資產 (也就是結尾為 .js 的 JavaScript 資產)。

舉例來說,main.js 可能會重新命名為 main.js.br

當應用程式重新載入並重新建構時,現在系統會建立主要套件的壓縮版本。開啟 Glitch 主控台,以查看節點伺服器提供的最終 public/ 目錄中的內容。

  1. 按一下「工具」按鈕。
  2. 按一下「Console」按鈕。
  3. 在主控台中執行下列指令,變更為 public 目錄,以查看當中的所有檔案:
cd public
ls -lh
使用靜態 Brotli 壓縮的軟體包大小

軟體包 main.bundle.js.br 的壓縮版本現在也儲存在此處,與 main.bundle.js 相比大小減少約 76% (225 KB,比 53 KB)。

接下來,指示伺服器在要求原始 JS 版本時傳送這些經過暴力壓縮的檔案。方法是在檔案透過 express.static 提供前,在 server.js 中定義新路徑。

var express = require('express');

var app = express();

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.br';
  res.set('Content-Encoding', 'br');
  res.set('Content-Type', 'application/javascript; charset=UTF-8');
  next();
});

app.use(express.static('public'));

app.get 用於指示伺服器如何回應特定端點的 GET 要求。接著,回呼函式會用於定義處理這項要求的方式。路線的運作方式如下:

  • '*.js' 指定為第一個引數,表示每個觸發端點都會執行此方法,以擷取 JS 檔案。
  • 在回呼中,.br 會附加至要求的網址,Content-Encoding 回應標頭則設為 br
  • Content-Type 標頭會設為 application/javascript; charset=UTF-8 以指定 MIME 類型。
  • 最後,next() 可確保該序列繼續進行任何可能的回呼。

由於部分瀏覽器可能不支援代理壓縮,因此請先檢查 Accept-Encoding 要求標頭包含 br,確認系統支援 brotli 壓縮後,再傳回亂數壓縮檔案:

var express = require('express');

var app = express();

app.get('*.js', (req, res, next) => {
  if (req.header('Accept-Encoding').includes('br')) {
    req.url = req.url + '.br';
    console.log(req.header('Accept-Encoding'));
    res.set('Content-Encoding', 'br');
    res.set('Content-Type', 'application/javascript; charset=UTF-8');
  }
  next();
});

app.use(express.static('public'));

應用程式重新載入後,請再次查看「網路」面板。

套件大小:53.1 KB (來自 225 KB)

大功告成!您已使用 Brotli 壓縮功能進一步壓縮素材資源!

結論

本程式碼研究室說明 brotli 如何進一步縮減應用程式的整體大小。如果支援,brotli 是比 gzip 更強大的壓縮演算法。