使用 brotli 壓縮網路酬載

麥可.迪布亞西歐 (Michael DiBlasio)
Michael DiBlasio

本程式碼研究室是壓縮及壓縮網路酬載程式碼研究室的延伸,並假設您熟悉壓縮的基本概念。與 gzip 等其他壓縮演算法相比,本程式碼研究室會探索 Brotli 壓縮功能如何進一步降低壓縮率和應用程式的整體大小。

應用程式螢幕截圖

測量

在開始新增最佳化作業之前,建議您先分析應用程式的目前狀態。

  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 開發人員工具「網路」分頁 (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'));

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

採用動態 Brotli 壓縮的組合大小

您現在可以在 Content-Encoding 標頭中看到從 bz 套用的 brotlimain.bundle.js 已從 225 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');

然後將其加入外掛程式陣列中:

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

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

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

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

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

  1. 按一下「工具」按鈕。
  2. 按一下「Console」按鈕。
  3. 在主控台中執行下列指令,將帳戶變更為 public 目錄,並查看當中的所有檔案:
cd public
ls -lh
組合大小和靜態 Brotli 壓縮

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

接著,指示伺服器在收到原始 JS 版本要求時傳送這些 brotli 壓縮檔案。只要在 server.js 中定義新路徑,再透過 express.static 提供檔案即可。

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() 可確保序列繼續進行接下來的任何回呼。

由於部分瀏覽器可能不支援 brotli 壓縮,因此在傳回 brotli 壓縮檔案前,請查看 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 更強大的壓縮演算法。