Search code examples
blazorseowebassemblyfluxorhosted-blazor-webassembly

Doesn't render anything of the Webassembly application when navigating the first time to the url


I don't know a lot of Blazor but I do have a problem that I think a lot of us are trying to solve.

I have a Blazor Webassembly application that I'm trying to prerender for improving the SEO. I implemented the following solution: https://andrewlock.net/enabling-prerendering-for-blazor-webassembly-apps/

So I have a Host and a Webassembly application. This application just shows a list of available jobs with the following information: jobtitle, region and tech stack. When you click on the card which is wrapped around an a tag, you navigate to the detail page of the job. In the Webassembly application I'm using Fluxor for store state. So this is already my first problem. It doesn't render anything of the Webassembly application when navigating the first time to the url. Only the things I placed in the following:

<div id="blazor-error-ui">
    <div class="header">
        <h1>Jobs</h1>
        <h2>Find a job!</h2>
    </div>
    An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">x</a>
</div>

As you can see in the network tab:

networkTab

My _Host.cshtml body looks like this:

<body>
    <div id="app">
        <component type="typeof(Craxit.Jobs.Blazor.App)" render-mode="WebAssemblyPrerendered" />
    </div>

    <div id="blazor-error-ui">
        <div class="header">
            <h1>Jobs</h1>
            <h2>Find a job!</h2>
        </div>
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="_content/MudBlazor/MudBlazor.min.js"></script>
    <script src="js/mask.js"></script>
    <script src="https://www.google.com/recaptcha/api.js"></script>
    <script src="js/googleRecaptcha.js"></script>
    <script>
        function scrollIntoView(elementId) {
            var elem = document.getElementById(elementId);
            if (elem) {
                elem.scrollIntoView({ behavior: 'smooth' });
                window.location.hash = elementId;
            }
        }
    </script>

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-73108595-3"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());
        gtag('config', 'UA-73108595-3');
    </script>
    <script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
    <script src="js/ShowCookieConsent.js"></script>
</body>

And in my webassembly application I have the following:

<Fluxor.Blazor.Web.StoreInitializer />

@if(GeneralState.Value.IsPermanent is not null)
{
    <Router AppAssembly="@typeof(App).Assembly" PreferExactMatches="@true">
        <Found Context="routeData">
            <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
}

Where in the code I load the jobs and place them in the store:

@code {        
    protected override void OnInitialized()
    {
        Dispatcher.Dispatch(new LoadContractFilterAction());
        base.OnInitialized();
    }
}

When also looking to the url with Lighthouse I get the following mention:

ResponseLighthouse

But I don't added a robot.txt file? Do I need to add it? Any idea where I can place it? The structure of my application is:

  • Client with the App that's rendered in the Server -> so I do think that the wwwroot is not used anymore? This clients contains the complete setup of the application.
  • Host with a _Host.cshtml -> place it here? This only refers to the client.

Also in the response of the ligthouse I saw that he says that the href needs to be linked to appropriate destinations. But this destinations are created with fluxor, so is it possible because of that?

Kind regards and thank you in advance!


Solution

  • Blazor WASM is not SEO friendly. But you can Control content in ASP.NET Core Blazor apps by adding dynamic meta tags (and other head elements) to your pages via Component Tag Helper, HeadContent, and HeadOutlet:

    There is HeadOutlet configured in Program.cs:

    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");
    builder.RootComponents.Add<HeadOutlet>("head::after");
    

    The HeadOutlet component renders content provided by PageTitle and HeadContent components. If you follow Prerender and integrate ASP.NET Core Razor components instructions you will get HeadOutlet component configured like this:

    <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />