question

PrtenjakMatja-1520 avatar image
0 Votes"
PrtenjakMatja-1520 asked PrtenjakMatja-1520 answered

Blazor WASM - serving js.gz

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)

windows-server-iisdotnet-aspnet-core-blazor
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered

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

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

PrtenjakMatja-1520 avatar image
0 Votes"
PrtenjakMatja-1520 answered SamWu-MSFT commented

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.



· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@PrtenjakMatja-1520

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

Use failed request tracing to see what is the difference between the modules of the two requests and you will know where the problem is.

0 Votes 0 ·
PrtenjakMatja-1520 avatar image
0 Votes"
PrtenjakMatja-1520 answered SamWu-MSFT commented

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.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@PrtenjakMatja-1520 Please check that you have failed request tracing enabled.

203885-2.png

0 Votes 0 ·
2.png (63.6 KiB)
Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered PrtenjakMatja-1520 commented

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://docs.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
     }
 });
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi,

most likely you have a webapi and static file handler hosting the blazor app.

No, It is blazor WASM app hosted in ISS. Just clasic app that can be hosted on any webserver (like appache or others).

0 Votes 0 ·
PrtenjakMatja-1520 avatar image
0 Votes"
PrtenjakMatja-1520 answered

It works!

Thank you very much

Greetings from Slovenija

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.