Update - 19th September 2024
After conversations with some helpful developers on the #blazor channel of the DotNetEvolution Discord server, I have given Blazor a bit more of my time. I've left the original post below, but here are my amended thoughts after more perseverance and reflection, and a bit of a "lightbulb moment".
Support & Documentation
I still feel that the documentation is lacking. The onboarding experience for new developers is very far away from what I have come to expect of front-end frameworks, though it is very typical of .NET documentation. It tries to remain impartial and unopinionated but in doing so becomes disjointed and difficult for developers new to Blazor to use for their learning.
After a lot of discussion, my recent experiences in the Blazor support channels has been much improved. There appears to be a small core of people who are trying their best to help.
Design, Styling and CSS
Tailwind support is still lacking. Using the Tailwind CLI directly, or using NPM and a node package to install and use Tailwind CSS seems to be the best approach, though this does take away somewhat from the "pure .NET" experience.
Additionally, I've found that, at least in the early days of using Blazor, it is easier to install and use a UI library such as MudBlazor than try to build everything yourself. While packages like this somewhat bridge the ecosystem gaps I see between Blazor and other front-end frameworks, and provide complex components that you can just drop in and use, they come with their own drawbacks.
For me, the main drawback of using these UI packages is that they are mostly using Material UI or some other internal design system by default and in a lot of cases you can't easily override their styling with Tailwind. It is possible to pass in other CSS classes with some of these libraries and components, but the results can be unpredictable.
This makes it a choice between using the library to save time developing your own complex components or using Tailwind for ease of styling.
The blockers I faced
In the original article below I talk about things that I found to be huge blockers. The number one thing I was thinking about when I wrote that was authentication. Specifically, handling OIDC authentication in Blazor with the new "InteractiveAuto" rendering and still being able to make authenticated requests to my separate API that is also authenticated via OIDC.
This seems to be a subject that is largely ignored or glossed over in courses, tutorials and documentation. I think most existing Blazor developers see it as "obvious" but for me, it was anything but.
This was the "lightbulb moment" I mentioned earlier. You don't need the access token in the Blazor Client project.
Let me explain...
Using a package called Microsoft.Extensions.ServiceDiscovery.Yarp you can configure a "Catch All" route in the Blazor Server application that will act as a reverse proxy for your API. For me, it looked like this:
app.MapForwarder("/api/{**catch-all}", apiBaseUrl, builder =>
{
builder.AddXForwardedFor();
builder.AddRequestTransform(async ctx =>
{
var originalPath = ctx.HttpContext.Request.Path.Value;
if (originalPath!.StartsWith("/api"))
{
var newPath = originalPath["/api/".Length..]; // Removes "/api"
ctx.ProxyRequest.RequestUri = new Uri($"{apiBaseUrl}{newPath}");
}
var accessToken = await ctx.HttpContext.GetTokenAsync("access_token");
if (!string.IsNullOrEmpty(accessToken))
ctx.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
});
});
This will add the X-Forwarded-For header to the request to ensure the API sees the end user's real IP and attaches the Authorization header and access token to the request automatically if the user is logged in.
In this scenario, you handle the authentication only on the server. A copy of the important claims in the ClaimsPrincipal can be passed to the client part of the application using Persistent Component State as shown in this example app. The server maintains the authentication state using a cookie which is passed up on any request from the Client to the Server with Blazor.
Once you grasp how this works, it's like magic!
To understand this more fully, look up the "BFF Pattern" or "Back-end for front-end pattern".
So what's my new conclusion?
Overall, I still think that Blazor is harder to learn than other front-end frameworks. However, I would amend my TL;DR; as follows:
- If you already work with JavaScript-based front-end frameworks, you probably don't need Blazor. But you might want to learn it to gain access to some of its cross-platform and native app possibilities and to expand your resumé.
- If you're a .NET developer looking to build front-end applications, give it a try. I'd still suggest learning a JavaScript framework too, so you have options and understand some of the finer points of how browsers work, but Blazor, once you "get it", allows you to build your entire application in a single tech stack.
Personally, I still have a great belief in using the best tool for the job. Blazor has become another tool in my belt and I'm glad I stuck with it this time around. I look forward to seeing what the Blazor team at Microsoft do with it next.
If I could only make one suggestion to Microsoft about Blazor, it would be this: Invest more in the community and ecosystem. More "end to end" tutorials to help fill in the gaps in the documentation, more "out of the box" components to help build apps faster and to act as examples, and more helpful people in the various community channels with a remit of helping new developers trying to learn Blazor and to get over the hurdles that we face. Take a leaf out of David Fowler's book from the Aspire project!
George Bernard Shaw
Progress is impossible without change, and those who cannot change their minds cannot change anything.
Original post:
Preface
I'm a .NET developer and have been for over 15 years. Before that, I worked mostly in PHP.
I say this, not to boast, but to give you an idea of what my biases might be. I've worked with .NET for a long time and have built many real-world production applications with it.
About 3 years ago I started learning how to use NextJS because I wanted to build API-first solutions and put nice, reactive front-end UIs on my apps. I've enjoyed using NextJS. I found the learning curve to be relatively shallow and the developer experience to be better than any other framework I've used.
However, Microsoft also has a front-end framework called Blazor that is supposed to be able to do all the same things as React, NextJS, Vue, etc. but using C# and .NET instead of Javascript.
TL;DR
- If you already know a JavaScript framework well enough to build your apps, stick with it and don't bother with Blazor.
- If you're a .NET developer looking to build front ends, maybe give it a try, but I suspect learning a JavaScript framework would be more time-efficient and productive in the long term (and is also a good thing on your resumé).
So what is Blazor?
Blazor is a web framework developed by Microsoft that allows developers to build interactive web applications using C# and .NET instead of JavaScript.
Blazor claims to enable the creation of client-side web applications with .NET, providing a rich, modern web development experience that allows existing .NET developers to leverage their existing skills and knowledge to build reactive front-end applications.
Sounds perfect for me, right? That's what I thought too, so I dove into creating a Blazor front-end for my new API in .NET 8.
What's the catch?
Well, there are a few.
- The documentation is terrible.
Throughout this project, I constantly found myself digging through Microsoft's documentation and examples only to discover that the examples don't work, are incomplete, or are specifically for Azure and won't work for non-Azure things. - The online support is almost non-existent
I posted my questions and issues to a number of places, including the "official" Blazor channel on the DotNetEvolution Discord server. I posted code examples, and detailed descriptions of what I was trying to do and the issues I was having.
In most cases, I got no responses at all. In some of the worst cases, I was ridiculed and belittled by people for not already knowing how to use Blazor. In the end, I was able to get some help from one specific Microsoft employee on the Discord server, but it took me to post a rant before that happened.
This is a trend I've noticed in the Blazor community - Only the people who whine and complain and cross-post their questions across multiple channels, often spamming them multiple times, get any attention or help. The people who follow the rules and post well-thought-out questions with code examples largely just get ignored. - No Tailwind CSS
I use Tailwind in most projects because I find it easy. It builds really small CSS bundles that don't bloat over time and are just a pleasure to use for any component-based framework.
Getting Tailwind working in Blazor is possible, but it's painful and you better be prepared to edit your *.csproj files and add new custom build targets. If you want the Tailwind "watch" functionality, be prepared to write a custom script and use their CLI. - Simple things become huge blockers
This is partly due to the terrible documentation and support, but as I was building my project I found that things that I take for granted in other frameworks just don't work in Blazor out of the box.
Environment Variables for example - you can't access them in the Blazor WASM client without doing a bunch of custom work to somehow pass them to it from the server.
By contrast, in NextJS you just prefix your environment variables with "NEXT_PUBLIC_" and boom - you can access them in your client components.
Another example is authentication. The documentation for OIDC authentication, and the examples they provide, just don't work in the WASM client.
Summary
I want to like Blazor. I really do. It has so much potential and would mean that I could build entire apps without leaving .NET. It would even simplify hiring for new developers since I'd be able to just focus on .NET.
In reality though, I just find myself hitting one roadblock after another and getting more and more frustrated.
In the time it took me to solve the issues with environment variables alone, I could have had my application halfway complete in NextJS.
Unfortunately, I can't see things getting better, nor can I see Blazor ever really competing with any of the major JavaScript frameworks.
While Microsoft continues to add new features and improve Blazor, the fundamental problem with it is the onboarding experience for new developers and the overall developer experience stemming from fragmented and incorrect documentation, paywalled tutorials and elitist community members who are unwilling to help.