使用Brotli提高網站訪問速度
在優化網站開啟速度上,我們有很多的方法,而其中一個就是減少諸如Javascript和CSS等資原始檔的大小,而減少檔案大小的方法除了在程式碼上下功夫外,最常用的方法就是使用壓縮演算法對檔案進行壓縮。
目前,網站普遍使用的是gzip壓縮演算法,但是最近兩年新興了一個新的壓縮演算法:Brotli,下面我將會對這個演算法進行簡單的介紹。
什麼是Brotli
Brotli是一個Jyrki Alakuijala和Zoltán Szabadka開發的開源資料壓縮程式庫, Brotli基於LZ77演算法的一個現代變體、霍夫曼編碼和二階上下文建模。最初釋出於2015年,用於網路字型的離線壓縮。Google軟體工程師在2015年9月釋出了包含通用無損資料壓縮的Brotli增強版本,特別側重於HTTP壓縮。其中的編碼器被部分改寫以提高壓縮比,編碼器和解碼器都提高了速度,流式API已被改進,增加更多壓縮質量級別。新版本還展現了跨平臺的效能改進,以及減少解碼所需的記憶體。
與常見的通用壓縮演算法不同,Brotli使用一個預定義的120千位元組字典。該字典包含超過13000個常用單詞、短語和其他子字串,這些來自一個文字和HTML文件的大型語料庫。預定義的演算法可以提升較小檔案的壓縮密度。
使用brotli取代deflate來對文字檔案壓縮通常可以增加20%的壓縮密度,而壓縮與解壓縮速度則大致不變。
WASM壓縮
釋出 Blazor WebAssembly 應用時,將在釋出過程中對輸出內容進行靜態壓縮,從而減小應用的大小,並免去執行時壓縮的開銷。 使用以下壓縮演算法:
- Brotli(級別最高)
- Gzip
Blazor 依賴於主機提供適當的壓縮檔案。 使用 ASP.NET Core 託管專案時,主機專案能夠執行內容協商並提供靜態壓縮檔案。 託管 Blazor WebAssembly 獨立應用時,可能需要額外的工作來確保提供靜態壓縮檔案:
有關 IIS web.config 壓縮配置,請參閱 IIS:Brotli 和 Gzip 壓縮 部分。
如果在不支援靜態壓縮檔案內容協商的靜態託管解決方案(例如 GitHub 頁面)上進行託管,請考慮配置應用以提取和解碼 Brotli 壓縮檔案:
從 google/brotli GitHub repository 中獲取 JavaScript Brotli 解碼器。 縮小的解碼器檔案被命名為 decode.min.js,並且位於儲存庫的 js 資料夾中。
更新應用以使用解碼器。
在 wwwroot/index.html 檔案中,在 Blazor 的 script 標記上將 autostart 設定為 false:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
在下面已經新增:
<script type="module">
import { BrotliDecode } from './decode.min.js';
Blazor.start({
loadBootResource: function (type, name, defaultUri, integrity) {
if (type !== 'dotnetjs' && location.hostname !== 'localhost') {
return (async function () {
const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
if (!response.ok) {
throw new Error(response.statusText);
}
const originalResponseBuffer = await response.arrayBuffer();
const originalResponseArray = new Int8Array(originalResponseBuffer);
const decompressedResponseArray = BrotliDecode(originalResponseArray);
const contentType = type ===
'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
return new Response(decompressedResponseArray,
{ headers: { 'content-type': contentType } });
})();
}
}
});
</script>
有關載入啟動資源的詳細資訊,請參閱 ASP.NET Core Blazor 啟動。
伺服器Nginx配置
執行nginx -V檢查是否帶br, 檢查 module= ngx_brotli
關鍵字. 如果不帶,自行編譯安裝.
nginx -V
nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.1.1k 25 Mar 2021
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/usr/src/ngx_brotli --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module
brotli 配置
# brotli 配置開始
brotli on;
brotli_comp_level 6; #壓縮等級,預設6,最高11,太高的壓縮水平可能需要更多的CPU
brotli_buffers 16 8k; #請求緩衝區的數量和大小
brotli_min_length 100; #指定壓縮資料的最小長度,只有大於或等於最小長度才會對其壓縮。這裡指定100位元組
brotli_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/json image/svg application/font-woff application/vnd.ms-fontobject application/vnd.apple.mpegurl image/x-icon image/jpeg image/gif image/png image/bmp; #指定允許進行壓縮型別
brotli_static always; #是否允許查詢預處理好的、以.br結尾的壓縮檔案,可選值為on、off、always
brotli_window 512k; #視窗值,預設值為512k
proxy_set_header Accept-Encoding "";
# brotli 配置結束
測試結果
新建預設wasm工程,非pwa
方式 | 釋出後 | rar壓縮包 | chrome 隱私模式 | edge隱私模式 | 備註 |
---|---|---|---|---|---|
WASM+BR | 15.5 m | 8.76 m | 1.87s | 2.09s | |
WASM AOT | 32.5 m | 16.2 m | 3.75s | 2.8s | |
WASM+BR (net7pre2) | 16.2 m | 9.05 m | 1.91s | 2.68s | net6工程升級 |
WASM AOT (net7pre2) | 27.7 m | 14.6 m | 2.54s | 2.69s | net6工程升級 |
WASM+BR (net7pre2) | 16.2 m | 9.23 m | 1.89s | 1.99s | 新建工程 |
WASM AOT (net7pre2) | 36.3 m | 17.3 m | 2.52s | 2.75s | 新建工程 |
結論
-
在不支援靜態壓縮檔案內容協商的靜態託管解決方案使用decode.min.js的確可以呼叫br解壓縮,在啟用br的nginx上就無需這個操作了,因為使用和不使用decode.min.js實際請求發傳送都是完全一致的.br檔案.
-
PWA方式是不能用decode.min.js的, 會直接會導致pwa離線功能失效. 在啟用br的nginx上就走nginx自己的br就夠了.會自動命中釋出的br資源.
技巧
提示hash校驗失敗, 可以強制關掉或者自己再算一遍
map(asset => new Request(asset.url, { cache: 'no-cache' }));
配圖
測試一: WASM + BR
測試二: WASM + AOT + BR
知識共享許可協議
本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名AlexChow(包含連結: https://github.com/densen2014 ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我聯絡 。