使用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 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。