使用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 ),不得用於商業目的,基於本文修改后的作品務必以相同的許可發布。如有任何疑問,請與我聯系 。