Why Blazor 8 prerendering does not render all of the page?

53 views Asked by At

I have a .NET 8 Blazor project using the new Auto rendering mode. I have this page that simply retrieves a forum's data from the ForumsService, a gRPC service client, and shows a simple loading screen when the request is being processed:

@page "/Forum/{ForumPermalink}"
@inject ForumsProto.ForumsProtoClient ForumsService
@rendermode InteractiveAuto

<h3>Forum @@ @ForumPermalink</h3>

@if(_forum is not null)
{
    <p>@_forum.Name</p>
}
else
{
    <Loading/> @* A simple component with only a p tag *@
}

@code {
    [Parameter]
    public string ForumPermalink { get; init; } = null!;

    private ForumReply? _forum;
    
    protected override async Task OnInitializedAsync()
    {
        try
        {
            _forum = await ForumsService.GetForumByPermalinkAsync(new()
            {
                Permalink = ForumPermalink
            });
        }
        catch(RpcException exception)
        {
            if(exception.StatusCode == StatusCode.NotFound)
            {
                NotFoundService.NotifyNotFound();
                return;
            }

            throw;
        }
    }

}

The Loading component:

<p>Please Wait...</p>

As of my knowledge, Blazor Auto render mode also has a feature called "Prerendering", that processes and sends an initial HTML to the client before any interaction starts, to improve the initial page load experience and also be bot-friendly, so Google and other bots can crawl the site.

My problem is simple, it doesn't work properly. When I "View Source" the page, this is what is displayed:

...

<body>
    <header>
<--- prerendered correctly -->
    </header>
    <h3>Forum @ {permalink value is fine}</h3>


    <div class="search-overlay" b-5zir38ipii>
...
    </div>
    <footer b-5zir38ipii>
<--- prerendered correctly -->
    </footer>
    <script src="/_framework/blazor.web.js"></script>
</body>
</html>

Neither the <p>@_forum.Name</p>, nor the <Loading/> component is even included in the HTML. Again, the page works fine when opened in a normal browser; But I want the forum name (and not even the loading component) to be included in the prerendering so that the site can be indexed as it should.

So my question is, how can I tell the prerenderer to wait for the forum in the OnInitializedAsync() method and include the _forum.Name, so the page is completely displayed to bots?

1

There are 1 answers

4
MrC aka Shaun Curtis On

The logic of this bit of code either renders the _forum.Name or the contents of <Loading/>. It can't do anything else.

@if(_forum is not null)
{
    <p>@_forum.Name</p>
}
else
{
    <Loading/> @* A simple component with only a p tag *@
}

So either <Loading/> renders nothing [which you say isn't true] or @_forum.Name is null or empty [in which case you should see <p></p>].

To assert this:

@if(_forum is not null)
{
    <div>Forum is not nothing</div>
}
else
{
    <div>Forum is nothing</div>
}