使用 brotli 壓縮網路酬載

Michael DiBlasio
Michael DiBlasio

本程式碼研究室是縮小及壓縮網路有效負載程式碼研究室的延伸內容,並假設您已熟悉壓縮的基本概念。相較於其他壓縮演算法 (例如 gzip),這個程式碼研究室會探討 Brotli 壓縮 (br) 如何進一步降低壓縮比,以及應用程式的整體大小。

應用程式螢幕截圖

測量

在開始新增最佳化項目之前,建議您先分析應用程式的現況。

  1. 按一下「Remix to Edit」,即可編輯專案。
  2. 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示 全螢幕

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

Brotli 壓縮

Brotli 是較新的壓縮演算法,可提供比 gzip 更優異的文字壓縮結果。根據 CertSimple 的資料,Brotli 的效能如下:

  • 比 JavaScript 專用 gzip 小 14%
  • 比 HTML 的 gzip 小 21%
  • 比 CSS 的 gzip 小 17%

如要使用 Brotli,伺服器必須支援 HTTPS。所有新式瀏覽器都支援 Brotli。支援 Brotli 的瀏覽器會在 Accept-Encoding 標頭中加入 br

Accept-Encoding: gzip, deflate, br

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

「網路」面板。「內容編碼」欄會顯示各種資產使用的編碼,包括 gzip 和 brotli (br)。

如何啟用 Brotli

設定網頁伺服器以傳送 Brotli 編碼資源的方式,取決於您打算如何編碼。您可以選擇在要求時使用 Brotli 動態壓縮資源 (動態),或提前編碼,讓資源在使用者要求時已壓縮 (靜態)。

動態壓縮

動態壓縮是指在瀏覽器要求資產時,即時壓縮資產。

優點

  • 您不必建立及更新素材資源的已儲存壓縮版本。
  • 即時壓縮特別適合動態產生的網頁。

缺點

  • 以較高層級壓縮檔案可提高壓縮比,但需要較長時間。這可能會導致效能下降,因為使用者必須等待資產壓縮完畢,伺服器才會傳送資產。

使用 Node 和 Express 進行動態壓縮

server.js 檔案負責設定代管應用程式的 Node 伺服器。

const express = require('express');
const app = express();
app.use(express.static('public'));

const 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

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

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

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

// Compress all requests
app.use(shrinkRay());
app.use(express.static('public'));

現在重新載入應用程式,並查看「Network」面板中的套件大小:

使用動態 Brotli 壓縮的套件大小。

您現在可以在 Content-Encoding 標題中看到 brotli 已從 bz 套用。 main.bundle.js225 KB 減少至 53.1 KB!這比 gzip (61.6 KB) 小約 14%。

靜態壓縮

靜態壓縮的概念是預先壓縮及儲存資產。

優點

  • 高壓縮層級造成的延遲問題已不復存在。現在可以直接擷取檔案,因此不需要即時壓縮檔案。

缺點

  • 每次建構時,都必須壓縮資產。如果使用高壓縮層級,建構時間可能會大幅增加。

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

由於靜態壓縮涉及預先壓縮檔案,因此可以修改 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');

並將其納入外掛程式陣列:

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

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

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

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

應用程式重新載入及重建時,系統會建立主要套件的壓縮版本。開啟 Glitch 控制台,查看 Node 伺服器提供的最終 public/ 目錄內容。

  1. 按一下「工具」按鈕。
  2. 按一下「控制台」按鈕。
  3. 在控制台中執行下列指令,切換至 public 目錄並查看所有檔案:
cd public
ls -lh
使用靜態 Brotli 壓縮的套件大小

現在,系統也會將套件的 brotli 壓縮版本 main.bundle.js.br 儲存於此,且大小比 main.bundle.js 小約 76% (225 KB 對上 53 KB)。

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

const express = require('express');
const 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() 會確保序列繼續執行下一個回呼 (如有)。

由於部分瀏覽器可能不支援 brotli 壓縮,請先確認支援 brotli,再傳回 brotli 壓縮檔案,方法是檢查 Accept-Encoding 要求標頭是否包含 br

const express = require('express');
const 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'));

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

組合大小為 53.1 KB (原為 225 KB)

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

結論

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