Blazor WASM - serving js.gz

Prtenjak Matjaž 21 Reputation points
2022-05-18T07:07:29.077+00:00

Hi,

I am using Blazor WASM. To prevent from serving old JS files if app changes, I am adding query parameter in the end, like:

  <script src="_framework/blazor.webassembly.js?cache_version=33"></script>

To use .BR or .GZ fles, I have web.config like this:

<?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=".json" mimeType="application/json" />
      <mimeMap fileExtension=".woff" mimeType="font/woff" />
      <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
      <mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".wasm" mimeType="application/wasm" />
      <mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
      <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>
    <httpCompression>
      <dynamicTypes>
        <remove mimeType="text/*" />
        <remove mimeType="application/javascript" />
        <remove mimeType="image/svg+xml" />
      </dynamicTypes>
      <staticTypes>
        <remove mimeType="text/*" />
        <remove mimeType="application/javascript" />
        <remove mimeType="image/svg+xml" />
      </staticTypes>
    </httpCompression>
    <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>
<handlers accessPolicy="Read, Script" />
    <urlCompression doStaticCompression="false" doDynamicCompression="false" />
  </system.webServer>
</configuration>

Problem

Requesting blazor.webassembly.js works fine. It uses blazor.webassembly.js.gz file and unpack it to javascript
Requesting blazor.webassembly.js?test does not work. It uses blazor.webassembly.js.gz file, but not unpack it to source, so it is seen as gzip bytes (as binary)

Internet Information Services
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,448 questions
0 comments No comments
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 58,936 Reputation points
    2022-05-20T15:26:49.24+00:00

    looked closer at your rewrite rules. your rewrite rule for adding the content encoding header,

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

    do not support query strings. have your rewrite rules remove the query string:

           <action type="Rewrite" url="{R:1}.br" appendQueryString="false" />
    
    0 comments No comments

4 additional answers

Sort by: Most helpful
  1. Prtenjak Matjaž 21 Reputation points
    2022-05-18T08:09:07.117+00:00

    I have found the reason, but not the solution.

    If I request

    http://xxxx/_framework/blazor.webassembly.js
    

    Server responses with

    Content-Encoding: gzip
    

    But, if I request

    http://xxxx/_framework/blazor.webassembly.js?Test
    

    there is no Content-Encoding header.


  2. Prtenjak Matjaž 21 Reputation points
    2022-05-19T09:01:39.067+00:00

    Hi,

    Thanks for your reply. But apparently there is nothing wrong with redirect.

    Folder FailedReqLogFiles was created, but it is empty no mather which URI I call.


  3. Bruce (SqlWork.com) 58,936 Reputation points
    2022-05-19T15:26:11.75+00:00

    most likely you have a webapi and static file handler hosting the blazor app. when the query string is added, the request is handled by the static file handler, not IIS.

    see docs to add the content encoding header:

    https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-6.0

    app.UseStaticFiles(new StaticFileOptions  
    {  
        OnPrepareResponse = ctx =>  
        {  
            // test if encoding header required and add header  
        }  
    });  
    

  4. Prtenjak Matjaž 21 Reputation points
    2022-05-23T06:14:39.237+00:00

    It works!

    Thank you very much

    Greetings from Slovenija

    0 comments No comments