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:
- 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!
BlazorWASMis notSEOfriendly. But you can Control content in ASP.NET Core Blazor apps by adding dynamicmetatags (and otherheadelements) to your pages via Component Tag Helper,HeadContent, andHeadOutlet:There is
HeadOutletconfigured in Program.cs:The
HeadOutletcomponent renders content provided byPageTitleandHeadContentcomponents. If you follow Prerender and integrate ASP.NET Core Razor components instructions you will getHeadOutletcomponent configured like this: