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