本程式碼研究室是「縮減及壓縮網路酬載」程式碼研究室的延伸課程,假設您熟悉壓縮的基本概念。與 gzip
等其他壓縮演算法相比,這個程式碼研究室會探討 Brotli 壓縮 (br
) 如何進一步降低壓縮比率和應用程式的整體大小。
測量
在著手新增最佳化功能前,建議您先分析應用程式的目前狀態。
- 按一下「Remix to Edit」,即可編輯專案。
- 如要預覽網站,請按下「View App」,然後按下「Fullscreen」。
在先前的壓縮網路酬載程式碼研究室中,我們將 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+I
或 Ctrl+Alt+I
) 中的 Content-Encoding
欄位,判斷要使用哪種壓縮演算法:
如何啟用 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
是從 bz
套用至 Content-Encoding
標頭。main.bundle.js
從 225 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');
並將其加入 plugins 陣列中:
module.exports = {
// ...
plugins: [
// ...
new BrotliPlugin({
asset: '[file].br',
test: /\.(js)$/
})
]
},
外掛程式陣列會使用下列引數:
asset
:目標資產名稱。[file]
會替換成原始素材資源檔案名稱。test
:系統會處理所有符合此規則運算式的資產 (也就是結尾為.js
的 JavaScript 資產)。
舉例來說,main.js
可能會重新命名為 main.js.br
。
當應用程式重新載入及重新建構時,系統會建立主要套件的壓縮版本。開啟 Glitch 控制台,查看 Node 伺服器提供的最終 public/
目錄內的內容。
- 按一下「工具」按鈕。
- 按一下「Console」按鈕。
- 在主控台中執行下列指令,切換至
public
目錄並查看所有檔案:
cd public
ls -lh
套件的 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」面板。
大功告成!您已使用 Brotli 壓縮功能進一步壓縮素材資源!
結論
本程式碼研究室說明 brotli
如何進一步縮減應用程式的整體大小。如果支援,brotli
是比 gzip
更強大的壓縮演算法。