• Blazor 发布WebAssembly使用Brotli 压缩提升初次加载速度


    使用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 新建工程

    结论

    1. 在不支持静态压缩文件内容协商的静态托管解决方案使用decode.min.js的确可以调用br解压缩,在启用br的nginx上就无需这个操作了,因为使用和不使用decode.min.js实际请求发发送都是完全一致的.br文件.

    2. PWA方式是不能用decode.min.js的, 会直接会导致pwa离线功能失效. 在启用br的nginx上就走nginx自己的br就够了.会自动命中发布的br资源.

    技巧

    提示hash校验失败, 可以强制关掉或者自己再算一遍

    map(asset => new Request(asset.url, {  cache: 'no-cache' }));
    

    配图

    测试一: WASM + BR

    测试一 WASM

    2 (480)
    3 (480)
    1 (608)
    4 (854)
    5 (750)

    测试二: WASM + AOT + BR

    测试二 WASM AOT

    2 (480)
    3 (480)
    1 (608)
    4 (854)
    5 (839)

    知识共享许可协议

    本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

    AlexChow

    今日头条 | 博客园 | 知乎 | Gitee | GitHub

  • 相关阅读:
    爬虫之BeautifulSoup4
    Vue混入与插件
    transformers 之 head介绍
    RocketMQ源码阅读(十四)延迟消息
    冯喜运:6.5黄金原油今日行情趋势分析及操作策略
    第10章 初识Spring MVC框架
    Rust入门-引用借用
    也谈SAP系统优缺点
    【Qt-23】基于QCharts绘制曲线图
    基于STM32蓝牙控制的app智能台灯设计
  • 原文地址:https://www.cnblogs.com/densen2014/p/16120778.html