ASP.NET Core Blazor with SignalR breaks when used with Cloudflare's HTML minification

ASP.NET Core Blazor with SignalR breaks when used with Cloudflare's HTML minification

Today's post is a short post with a tip. Recently we faced an issue with using ASP.NET Core Blazor together with Cloudflare when going into production.

TLDR:

  • The desired outcome is a working SignalR-based Blazor site.
  • The actual outcome was a broken SignalR-based Blazor site. SignalR couldn't connect.
  • Root cause: Cloudflare minified the HTML, removing the HTML comments that are required for Blazor Signal R.

Here are the details.

Desired outcome

When setting up a new basic Blazor project using the default template, the outcome I desire and expect in the HTML source is this:



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>CloudFlareTest</title>
    <base href="/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
</head>
<body>
    <app>
        <!--Blazor:{"sequence":0,"type":"server","prerenderId":"84875b90afa94d25a0fcca8aa7c114d4","descriptor":"CfDJ8FC1j1fh78VIoUwVT7Ma1kQY0tjbKWj6D2x1aRAAnmK3K\u002BtykFbM3zY6ejjQkkingGMmwgKNBwrSxhC5rT33oRh4/VnvvNrSocn8PsULSSZgWX5cCuOiDgBVfaTfonvYt7wsRMkBcT9kbwfJBXXjK8QQDbOOg12Z57/Pyc4\u002BhmU3wV3KZDoyroBlywRDpypDBv/6dJOG/GC/cecDu1pehxDb7OxK3CFRdwoO5EJMVhiZ2ULQRb2hqKnnrq695iv2J4OdormN1wmly3E0GKn6ccr04bFHBfELRIblb31M3uxNtL8NGCoujMClg3bU0ISguBV9LTcY78AKe6dVkeO9GeDTVCJ\u002BY27valgYGPgHX12R"}-->
        <div class="sidebar">
    <div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href>CloudFlareTest</a>
    <button class="navbar-toggler">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="collapse">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <a href="" class="nav-link">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </a>
        </li>
        <li class="nav-item px-3">
            <a href="counter" class="nav-link active">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </a>
        </li>
        <li class="nav-item px-3">
            <a href="fetchdata" class="nav-link">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </a>
        </li>
    </ul>
</div>
</div>

<div class="main">
    <div class="top-row px-4">
        <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
    </div>

    <div class="content px-4">
        <h1>Counter</h1>

<p>Current count: 0</p>

<button class="btn btn-primary">Click me</button>
    </div>
</div>
    <!--Blazor:{"prerenderId":"84875b90afa94d25a0fcca8aa7c114d4"}-->
    </app>

    <div id="blazor-error-ui">
        
            An error has occurred. This application may no longer respond until reloaded.
        
        
        <a href="" class="reload">Reload</a>
        <a class="dismiss">đź—™</a>
    </div>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>

If you pay attention to the HTML comments here, you'll see these lines:

<!--Blazor:{"sequence":0,"type":"server","prerenderId":"84875b90afa94d25a0fcca8aa7c114d4","descriptor":"CfDJ8FC1j1fh78VIoUwVT7Ma1kQY0tjbKWj6D2x1aRAAnmK3K\u002BtykFbM3zY6ejjQkkingGMmwgKNBwrSxhC5rT33oRh4/VnvvNrSocn8PsULSSZgWX5cCuOiDgBVfaTfonvYt7wsRMkBcT9kbwfJBXXjK8QQDbOOg12Z57/Pyc4\u002BhmU3wV3KZDoyroBlywRDpypDBv/6dJOG/GC/cecDu1pehxDb7OxK3CFRdwoO5EJMVhiZ2ULQRb2hqKnnrq695iv2J4OdormN1wmly3E0GKn6ccr04bFHBfELRIblb31M3uxNtL8NGCoujMClg3bU0ISguBV9LTcY78AKe6dVkeO9GeDTVCJ\u002BY27valgYGPgHX12R"}-->

<!--Blazor:{"prerenderId":"84875b90afa94d25a0fcca8aa7c114d4"}-->

These comments are used by Blazor to wire things up. Keep this in mind as we walk further down the rabbit hole.

The problem with Cloudflare

Using Cloudflare is fantastic. It is easy to configure, and it helps with performance, and it's boosting many of our web-based workloads.

Speaking of optimizations, we always do "Auto minify," which is an option under Speed - Optimization in Cloudflare:

Cloudflare optimizations for page speed. Auto minify JavaScript, CSS and HTML.

Usually, this is an excellent experience except when building Blazor web applications that make use of Web Sockets to communicate using SignalR.

The outcome then rips the, apparently necessary, HTML comments right out of the source page. This minification results in a minified HTML page, and the same app service is now serving this HTML content instead. Note that all HTML comments are missing:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CloudFlareTest</title>
<base href="/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>

<div class="sidebar">
<div class="top-row pl-4 navbar navbar-dark">
<a class="navbar-brand" href>CloudFlareTest</a>
<button class="navbar-toggler">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="collapse">
<ul class="nav flex-column">
<li class="nav-item px-3">
<a href="" class="nav-link">
<span class="oi oi-home" aria-hidden="true"></span> Home
</a>
</li>
<li class="nav-item px-3">
<a href="counter" class="nav-link active">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</a>
</li>
<li class="nav-item px-3">
<a href="fetchdata" class="nav-link">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</a>
</li>
</ul>
</div>
</div>
<div class="main">
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<div class="content px-4">
<h1>Counter</h1>
<p>Current count: 0</p>
<button class="btn btn-primary">Click me</button>
</div>
</div>

</app>
<div id="blazor-error-ui">
An error has occurred. This application may no longer respond until reloaded.
<a href="" class="reload">Reload</a>
<a class="dismiss">đź—™</a>
</div>
<script src="_framework/blazor.server.js"></script>
</body>
</html>

Fix: Set up a custom Page Rule to exclude HTML minification

With Cloudflare, you could, of course, disable HTML minification on the entire domain. That is not my desired state, and hence I am looking for other ways to improve the experience to only on the given subdomain I am deploying.

Enter Cloudflare Page Rules.

Heading over to Page Rules, I can define a new rule, saying that my subdomain "app.mydomain.com" should NOT minify HTML. I have left CSS, and JS enabled in order to boost performance as much as I can with that content.

Here are the settings necessary.

Configuring a Page Rule to avoid HTML minification when using ASP.NET Blazor.

Voila - with that in place, the deployed ASP.NET Blazor experience is back on track and works.

  • SignalR and web sockets can communicate.
  • HTML Comments are present in the page source.
  • Connections are working.

Header photo by israel palacio on Unsplash

Sign up to my newsletter!

* indicates required

About Tobias Zimmergren

Hi, I'm Tobias. I plan, architect and develop software and distributed cloud services. Nice to meet you!

Comments