I recently got my first real chance to play around with Blazor beyond “hello world” (yay hackathons!). Previously I’ve seen talks, read the odd blog post and gone through the samples but this was the first time I had used it with a purpose and I wanted to see whether or not we should be looking at it for “real” projects.
These are my first impressions…
Learning Curve? What Learning Curve?
The first thing I noted down was “wow, this is easy!”: if you’ve worked with any of the various ASP.NET Core MVC/razor pages/other UI approaches then everything here will be incredibly familiar.
The samples get you up & running quickly and they’re not creating a load of boilerplate to get you started: the generated code is terse and (with the exception of fairly heavy CSS) there’s not a lot to strip out if you want to get back to a clean start.
The C# side of things seemed to “just work”: I added nuget packages, my own libraries, plugged it all into the DI container and it worked seamlessly without any special effort on my part.
Those Docs! 🤩
I spend a lot of my time these days in the world of React, and my process for solving an unfamiliar problem is usually:
- Google the problem
- Scan through the 3 or 4 competing projects that try to solve the problem
- Take an educated guess at the best choice
- Make a note to try out the other 3 later to compare
It is incredibly refreshing to go to a single source of high-quality documentation and find the canonical approach explained in detail. The ASP.NET Core docs are pretty fantastic generally so there’s no surprise that the quality is high, but the removal of decision making - particularly when you’re not familiar with the ecosystem - is a huge accelerator.
Perhaps this will change as Blazor gains traction and more third party libraries pop up, but for now it’s great to find the answer to “how do I do X?” to be “like this. this is how you do X”.
It also helps that the solutions for most of those problems seem pretty smart…
Familiar Problems; Nice Solutions
Blazor obviously shares a bunch of problems with other SPA frameworks, and you can see the influence of existing frameworks in how those have been solved.
I briefly looked at Blazor in the early days. At that stage they didn’t have any solution to CSS besides global stylesheets for the app, which (compared to modular CSS from the React world) felt quite limiting. I asked this question of Steve Sanderson after a conference talk and his response boiled down to “yes, we know, and we’re working on it”.
Coming back to the project now, that’s exactly what it feels like: that they looked at existing solutions, thought about the generalised requirements and came up with a really nice approach.
The outcome is very reminiscent of CSS modules in React, but without the imports. For
MyView.razor you create a
MyView.razor.css and the CSS in that file is automatically bundled up and included in your build. The CSS definitions are scoped to that component (with an escape hatch if you want to affect child components) and you can still use globally-defined CSS variables for e.g. theming.
Apparently there is also support for SASS or LESS preprocessors, but I’ve not yet had cause to look into them.
Overall, the CSS implementation worked well and caused me no pain whatsoever. I started out thinking this might be a weak point but I walked away impressed.
Another example of borrowing good ideas from other libraries is that of
CascadingValues, which appear very similar to React Context.
Both approaches allow you to define a value in a
Provider somewhere in your component hierarchy and then access that value lower down the hierarchy in one or more consumers.
<Provider theme="dark"> <Deeply> <Nested> <Consumer /> <!-- this needs to get the value `dark` --> </Nested> </Deeply> </Provider>
The Blazor solution is familiar and simple to implement. I particularly like the way that the parent component can set the value to
this, allowing consumers rich interactions with the parent with very little extra code.
A few other things that I didn’t touch on too much but that seemed like nice solutions:
- Authentication (using AAD) was simple to set up and easy enough to integrate into my components
- The form components - for my very basic use cases - worked well
- Routing was incredibly easy, working almost exactly as it does in razor pages
Overall I found the tooling around Blazor to be… ok. Some parts are so good as to be essentially invisible (like the seamless WASM build & DI) but some parts did trip me up.
😥 No Debugging in Rider
I usually prefer Rider to Visual Studio and while you can build and run the Blazor projects you cannot debug them at all. It’s coming but it’s not available yet, so I ended up using Visual Studio and getting annoyed by all of the missing magic that Rider brings along.
As an alternative I did try the browser debugging but for some reason found it was almost unusably slow on my machine. I imagine this could be fixed with some investigation but I didn’t dig much further.
🐌 No Hot Reload
React (and others) have had hot reloading out-of-the-box for so long that I had started to take it for granted. Trying to make minor tweaks to CSS with a full stop/build/run/navigate-to-the-page cycle in between was a huge pain, but as far as I can tell there is no first-class support for live updates.
The closest I could get was to run
dotnet watch run in a separate terminal. That comes at the expense of any debugging, but it does give hot reloading of CSS and C# changes and it does so very quickly (though maybe only because this project was so small).
As with other things on this list, it’s very possible that there is a better solution to this problem but it wasn’t obvious and I ran out of time.
I am pretty excited to play around more with Blazor. I’m not quite convinced that it’s ready for production, but I’m yet to find any concrete reasons why it is not.
I didn’t get a chance to dig into the publishing process, I have no idea about production bundle sizes and I haven’t looked at JS interop yet; those are next on my list. If that all looks good then I’m going to search out a candidate project to try it out “for real”.