nAviD
nAviD

Reputation: 3281

Blazor Webassembly Brotli and Gzip compression on IIS

As a Blazor developer I don't think there is a good documentation on this topic. I have uploaded a very simple Blazor webassembly(v5) website with only 1 page now it takes more than 20 seconds to load in browser. I tried to use compression based on this Microsoft doc and used the web.config file suggested by the document. I have also installed URL Rewrite module, Microsoft IIS Compression, StaticCompresstionModule and DynamicCopressionModule and tried modifying the web.config's following lines but it did not worked at all :

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" />
....

The result still is not compressed and here is my browser's developer tool screenshot :

enter image description here

This can be a problem for everyone who uses Blazor as the front-end. Can any one please provide a step-by-step working answer ?

Update : here is my final web.config (which does not work):

<?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>

Upvotes: 1

Views: 6267

Answers (3)

Ion Robu
Ion Robu

Reputation: 11

I started investigating the problem using this topic, and this is by far the best web.config I found: https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/host-and-deploy/webassembly/_samples/web.config It worked like a charm: the initial loading time (no browser cache) was shorted from ~20 seconds to ~1.2 seconds. My configuration is as above: IIS hosted Blazor client application.

Upvotes: 1

tebete
tebete

Reputation: 1

First, you need to follow prerequisites steps that Sasha mentioned. After compression already set on server, modify the web.config using web.config mentioned in options 2.

Don't forget add this line in your web.config

<remove fileExtension=".wasm" />

Before I added the above, my apps got an error when loading.

After that, you can clear your browser cache and history to test it.

Upvotes: 0

Sasha
Sasha

Reputation: 1017

TL;DR

Most likely you have a site misconfiguration issue in IIS. To confirm it, please check if your site configuration will load in Configuration Editor:

error-in-configuration-editor

  1. Select your website
  2. Double-click on Configuration Editor
  3. Check if this gives you an error

Then work your way through the errors and eliminate them one by one by updating your site configuration.

The challenge is that it's hard to provide a universally working example since it depends on many unknowns: OS version, IIS version, existing configs, etc.

Detailed steps

There are two ways for how it can be done: using IIS Compression scheme providers (Option 1) or using rewrites (Option 2).

Prerequisites

Here is what I used for my setup:

  • Windows 10 Pro
  • IIS version 10.0
  • Installed URL Rewrite Module
  • Dynamic Content Compression and Static Content Compression IIS features are enabled in Turn Windows features on or off dialog
  • New Blazor app created with .NET5.0 dotnet new blazorwasm

Option 1: Adding compression using IIS Compression scheme providers

  1. Install Microsoft IIS Compression

  2. Update your site configuration

    Note: it seems like the suggested configuration won't work by default in IIS. I had to remove some entries from it because they were duplicates of the entries in the IIS machine config.

Here is a configuration that finally worked for me:

<?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>

Option 2: Adding compression using rewrites

  1. Download the web.config provided in this article

  2. Go through similar activities as above, eliminating all web.config inconsistencies.

    Note: In my case, I had to remove mimeMap for .wasm due to duplication reported by IIS:

    ...
    <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" />
      ...
    

Results

And as a result, for either option, you should be able to see the following.

  • for HTTP

    result-http

  • for HTTPs

    result-https

Upvotes: 1

Related Questions