本程式碼研究室是壓縮及壓縮網路酬載程式碼研究室的延伸,並假設您熟悉壓縮的基本概念。與 gzip
等其他壓縮演算法相比,本程式碼研究室會探索 Brotli 壓縮功能如何進一步降低壓縮率和應用程式的整體大小。
測量
在開始新增最佳化作業之前,建議您先分析應用程式的目前狀態。
- 按一下「Remix to Edit」,讓專案可供編輯。
- 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示 。
在先前的壓縮網路酬載程式碼研究室中,我們已將 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
動態壓縮
動態壓縮必須在瀏覽器收到要求時即時壓縮素材資源。
優點
- 您無需建立及更新已儲存的資產壓縮版本。
- 即時壓縮功能特別適合用於動態產生的網頁。
缺點
- 壓縮較高層級的檔案才能有更好的壓縮率,需要較長時間。使用者會先等待素材資源壓縮,然後再由伺服器傳送,這可能會導致效能命中。
使用 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」面板中查看套件大小:
您現在可以在 Content-Encoding
標頭中看到從 bz
套用的 brotli
。main.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/
目錄中的內容。
- 按一下「工具」按鈕。
- 按一下「Console」按鈕。
- 在主控台中執行下列指令,將帳戶變更為
public
目錄,並查看當中的所有檔案:
cd public
ls -lh
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'));
應用程式重新載入後,請再次查看「網路」面板。
太好了,您已使用 Brotli 壓縮功能進一步壓縮素材資源!
結語
本程式碼研究室會說明如何利用 brotli
進一步縮減應用程式的整體大小。在支援的情況下,brotli
是比 gzip
更強大的壓縮演算法。