IIS 上的 Blazor Webassembly Brotli 和 Gzip 压缩

Posted

技术标签:

【中文标题】IIS 上的 Blazor Webassembly Brotli 和 Gzip 压缩【英文标题】:Blazor Webassembly Brotli and Gzip compression on IIS 【发布时间】:2021-12-16 02:24:28 【问题描述】:

作为 Blazor 开发人员,我认为没有关于此主题的好的文档。 我上传了一个非常简单的 Blazor webassembly(v5) 网站,只有 1 个页面,现在在浏览器中加载需要 20 多秒。我尝试使用基于thisMicrosoft doc 的压缩,并使用了文档建议的web.config 文件。 我还安装了 URL 重写模块 Microsoft IIS Compression、StaticCompresstionModule 和 DynamicCopressionModule 并尝试修改 web.config 的以下行,但它根本不起作用:

web.config:

...
 <httpCompression  directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
    <scheme name="br" dll="%ProgramFiles%\IIS\IIS Compression\iisbrotli.dll" />
     <scheme name="gzip" dll="%ProgramFiles%\IIS\IIS Compression\iiszlib.dll" />
....

结果仍然没有压缩,这是我浏览器的开发者工具截图:

这对于使用 Blazor 作为前端的每个人来说都是一个问题。 谁能提供一步一步的工作答案?

更新:这是我的最终 web.config(不起作用):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <remove fileExtension=".blat" />
      <remove fileExtension=".dat" />
      <remove fileExtension=".dll" />
      <remove fileExtension=".json" />
      <remove fileExtension=".wasm" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".json" mimeType="application/json" />
      <mimeMap fileExtension=".wasm" mimeType="application/wasm" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff" />


 

      <mimeMap fileExtension=".js.gz" mimeType="application/javascript" />
      <mimeMap fileExtension=".dat.gz" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".json.gz" mimeType="application/json" />
      <mimeMap fileExtension=".wasm.gz" mimeType="application/wasm" />
      <mimeMap fileExtension=".blat.gz" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".html.gz" mimeType="text/html" />
      <mimeMap fileExtension=".css.gz" mimeType="text/css" />
      <mimeMap fileExtension=".ico.gz" mimeType="image/x-icon" />
      <mimeMap fileExtension=".svg.gz" mimeType="image/svg+xml" />
      <mimeMap fileExtension=".js.br" mimeType="application/javascript" />
      <mimeMap fileExtension=".dat.br" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dll.br" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".json.br" mimeType="application/json" />
      <mimeMap fileExtension=".wasm.br" mimeType="application/wasm" />
      <mimeMap fileExtension=".blat.br" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".html.br" mimeType="text/html" />
      <mimeMap fileExtension=".css.br" mimeType="text/css" />
      <mimeMap fileExtension=".ico.br" mimeType="image/x-icon" />
      <mimeMap fileExtension=".svg.br" mimeType="image/svg+xml" />
    </staticContent>
 <rewrite>
      <outboundRules rewriteBeforeCache="true">
        <rule name="Add Vary Accept-Encoding" preCondition="PreCompressedFile" enabled="true">
          <match serverVariable="RESPONSE_Vary" pattern=".*" />
          <action type="Rewrite" value="Accept-Encoding" />
        </rule>
        <rule name="Add Encoding Brotli" preCondition="PreCompressedBrotli" enabled="true" stopProcessing="true">
          <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
          <action type="Rewrite" value="br" />
        </rule>
        <rule name="Add Encoding Gzip" preCondition="PreCompressedGzip" enabled="true" stopProcessing="true">
          <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
          <action type="Rewrite" value="gzip" />
        </rule>
        <preConditions>
          <preCondition name="PreCompressedFile">
            <add input="HTTP_URL" pattern="\.(gz|br)$" />
          </preCondition>
            <preCondition name="PreCompressedBrotli">
            <add input="HTTP_URL" pattern="\.br$" />
          </preCondition>
          <preCondition name="PreCompressedGzip">
            <add input="HTTP_URL" pattern="\.gz$" />
          </preCondition>
        </preConditions>
      </outboundRules>
      <rules>
        <rule name="Serve subdir">
          <match url=".*" />
          <action type="Rewrite" url="wwwroot\R:0" />
        </rule>
        <rule name="Rewrite brotli file" stopProcessing="true">
          <match url="(.*)"/>
          <conditions>
            <add input="HTTP_ACCEPT_ENCODING" pattern="br" />
            <add input="REQUEST_FILENAME" pattern="\.(js|dat|dll|json|wasm|blat|htm|html|css|ico|svg)$" />
            <add input="REQUEST_FILENAME.br" matchType="IsFile" />
          </conditions>
          <action type="Rewrite" url="R:1.br" />
        </rule>
        <rule name="Rewrite gzip file" stopProcessing="true">
          <match url="(.*)"/>
          <conditions>
            <add input="HTTP_ACCEPT_ENCODING" pattern="gzip" />
            <add input="REQUEST_FILENAME" pattern="\.(js|dat|dll|json|wasm|blat|htm|html|css|ico|svg)$" />
            <add input="REQUEST_FILENAME.gz" matchType="IsFile" />
          </conditions>
          <action type="Rewrite" url="R:1.gz" />
        </rule>
        <rule name="SPA fallback routing" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="REQUEST_FILENAME" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="wwwroot\" />
        </rule>
      </rules>
    </rewrite>
    <httpCompression>
      <dynamicTypes>
        <add mimeType="application/octet-stream" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/wasm" enabled="true" />
        <add mimeType="application/font-woff" enabled="true" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="application/octet-stream" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/wasm" enabled="true" />
        <add mimeType="application/font-woff" enabled="true" />
      </staticTypes>
    </httpCompression>
  </system.webServer>
</configuration>

【问题讨论】:

部署后第一次访问或者闲置一段时间后,确实需要一段时间才能得到响应。 IIS需要创建一个进程为应用程序分配CPU资源和内存空间,让应用程序先在服务器上运行,然后将css、脚本文件等资源缓存到客户端。 为什么你认为它没有被压缩?您的屏幕截图显示 24MB 资源的 10MB 传输大小 - 因此某些内容被压缩。您是否检查了其中一个 dll 文件的请求/响应,以查看您的浏览器说它可以接受什么压缩以及服务器响应了什么?也许分享一下,因为它比单独的概述更有用。 @MisterMagoo 因为我已经停止了这张照片的下载,而且文档说如果 dll 被压缩,你应该在浏览器的内容编码中看到“br”或“gzip”。 为什么首先加载需要 20 秒?你想建立什么样的网站?您是否尝试过将您的应用拆分为延迟加载的程序集? 检查浏览器的初始 HTTP 请求标头,是否将 Accept-encoding 设置为接受 br、gzip 等? 【参考方案1】:

TL;DR

您很可能在 IIS 中遇到了站点配置错误的问题。要确认它,请检查您的站点配置是否会在Configuration Editor 中加载:

    选择您的网站 双击Configuration Editor 检查这是否会给您带来错误

然后通过更新站点配置来解决错误并一一消除它们。

挑战在于很难提供一个通用的示例,因为它取决于许多未知因素:操作系统版本、IIS 版本、现有配置等。

详细步骤

有两种方法可以做到这一点:使用 IIS 压缩方案提供程序(选项 1)或使用重写(选项 2)。

先决条件

这是我用于设置的内容:

Windows 10 专业版 IIS 10.0 版 已安装URL Rewrite Module Dynamic Content CompressionStatic Content Compression IIS 功能 are enabled 在 Turn Windows features on or off 对话框中 使用 .NET5.0 创建的新 Blazor 应用 dotnet new blazorwasm

选项 1:使用 IIS 压缩方案提供程序添加压缩

    InstallMicrosoft IIS 压缩

    更新您的网站配置

    注意:似乎建议的configuration 在默认情况下在 IIS 中不起作用。我不得不从中删除一些条目,因为它们与 IIS 机器配置中的条目重复。

这是一个最终对我有用的配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <remove fileExtension=".blat" />
      <remove fileExtension=".dat" />
      <remove fileExtension=".dll" />
      <remove fileExtension=".json" />
      <remove fileExtension=".wasm" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".json" mimeType="application/json" />
      <mimeMap fileExtension=".wasm" mimeType="application/wasm" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff" />
    </staticContent>
    <rewrite>
      <rules>
        <rule name="Serve subdir">
          <match url=".*" />
          <action type="Rewrite" url="wwwroot\R:0" />
        </rule>
        <rule name="SPA fallback routing" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="REQUEST_FILENAME" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="wwwroot\" />
        </rule>
      </rules>
    </rewrite>
    <urlCompression doStaticCompression="true" doDynamicCompression="true" />
    <httpCompression>
      <dynamicTypes>
        <add mimeType="application/octet-stream" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/wasm" enabled="true" />
        <add mimeType="application/font-woff" enabled="true" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="application/octet-stream" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/wasm" enabled="true" />
        <add mimeType="application/font-woff" enabled="true" />
      </staticTypes>
    </httpCompression>
  </system.webServer>
</configuration>

选项 2:使用重写添加压缩

    下载this article中提供的web.config

    完成与上述类似的活动,消除所有web.config 不一致。

    注意:在我的例子中,由于 IIS 报告了重复,我不得不为 .wasm 删除 mimeMap

    ...
    <staticContent>
      <remove fileExtension=".dll" />
      <remove fileExtension=".json" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <remove fileExtension=".wasm" /> <!-- added this line -->
      <mimeMap fileExtension=".json" mimeType="application/json" />
      ...
    

结果

因此,对于任一选项,您应该能够看到以下内容。

用于 HTTP

对于 HTTPs

【讨论】:

谢谢我明天会检查你的答案。如果赏金到期,我将添加另一个赏金并将其提供给您。 很遗憾这没有用。 有趣。因此,如果您选择选项 1,您可以打开配置编辑器吗?当你这样做时,你可以切换到system.webServer/httpCompression 部分吗?如果可以,请检查以下属性:(Collection) 应包含 brgzip 方案,dynamicTypesststicTypes 应列出正确的 mimeTypes(例如 application/octet-stream 等)。 还有一点,有时 IIS 需要完全重启才能应用配置。您可以通过运行 iisreset.exe /restart 在管理员命令提示符下执行此操作。 它没有 httpCompression 部分【参考方案2】:

首先,您需要遵循 Sasha 提到的先决条件步骤。 在服务器上已经设置压缩后,使用选项 2 中提到的 web.config 修改 web.config。

不要忘记在你的 web.config 中添加这一行

<remove fileExtension=".wasm" />

在添加上述内容之前,我的应用在加载时出错。

之后,您可以清除浏览器缓存和历史记录以进行测试。

【讨论】:

以上是关于IIS 上的 Blazor Webassembly Brotli 和 Gzip 压缩的主要内容,如果未能解决你的问题,请参考以下文章

具有个人帐户和托管 ASP.NET Core 的 Blazor WebAssembly 应用程序 - IIS - SQLLocalDB 15.0 找不到指定的资源语言 ID

使用 gRPC 服务器作为主机调试 Blazor Webassembly

IIS 上的 Blazor 主机显示空白页

Blazor WASM - IIS 上的独立部署

初尝 Blazor WebAssembly

初尝 Blazor WebAssembly