DEV Community

Cover image for Why build Single Page Apps in Blazor
David Pine 🤓 for .NET

Posted on • Edited on

Why build Single Page Apps in Blazor

📚 In this post, we'll address some common Blazor questions. Specifically, the "what?", but more importantly the "why?". Why should I care about Blazor when we've already got Angular, React, Vue, or some other JavaScript framework? Why choose Blazor, and what is WebAssembly all about? We'll cover the history of Microsoft's web application development frameworks and what we see for its bright future 🔮.

🔥 What is Blazor?

There are several common definitions for Blazor, the first of which is rather straightforward:

"Blazor is a framework for building interactive client-side web UI with .NET."

Microsoft docs: Blazor

As the official docs state, it's a "framework" first — and it's used to build client-side web UI. But how is that different from any other client-side framework for building web UI, and what makes it so special? I'm hopeful that you're asking yourself, "does .NET make a difference?".

Here's another definition:

"Blazor is a free and open-source web framework that enables developers to create web apps using C# and HTML."

Wikipedia: Blazor

Oh, it's free — that's nice. But to be fair, there are plenty of other free frameworks for building client-side web UI. Why should I care about Blazor?

⁉ Why Blazor?

Historically, all of the prior web UI frameworks from Microsoft were based on an entirely different architecture and were rendered on the server-side. Blazor set out to bring C# development to the web client, and this was only going to be possible with the advent of WebAssembly.

"WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications."

webassembly.org

🤓 Wow, that sounds like a mouthful! Let's break that down a bit:

A "binary instruction format" in this case means that it's byte code, taking your abstract syntax tree (AST) from your non-JavaScript programming language and converting it to binary.

AST to binary

Wasm sits atop a "stack-based virtual machine" — this identifies the core functionality which is "push" ⬇ and "pop" ⬆ based. Instructions are pushed, and evaluations are popped. While this is an oversimplification, the concepts remain and the implementation details are less important. There are limitations with being single-threaded, applied memory constraints, and so on, but concerns are deemphasized as Blazor manages the interop to Wasm.

It's very important to call attention to the fact that Wasm is a "portable compilation target" 🎯. This means it's possible to take C, C++, Rust, C#, and other non-traditional web programming languages and target Wasm for their compilation. This results in Wasm binaries, which are web-ready based on open standards but from programming languages other than JavaScript.

To be clear, there is JavaScript interop and there are even different hosting models for Blazor — server-side or client-side with Wasm. More on that later...

😵 What about JavaScript?

Is Wasm the death 💀 of JavaScript, what does this mean? The answer is no. JavaScript isn't going anywhere — and Wasm should be considered complementary to JavaScript.

WebAssembly and JavaScript

"It is expected that JavaScript and WebAssembly will be used together in a number of configurations"

webassembly.org: FAQ

🆕 The analogy

Thanks to Wasm, the web browser has a few of its perceived limitations lifted, and this is why I believe:

"With WebAssembly, web browsers are more like app stores — where the end-user experience is more near-native performance."

David Pine

There are seemingly countless new use cases specific to Wasm that were not realistically achievable with JavaScript alone. It's easy to imagine applications being delivered over the web to your browser, powered by Wasm for more elaborate and resource-intensive use cases. This is why I believe it's a paradigm shift in what's possible with the web application platform.

🗺 Adoption

Wasm is supported in all major browsers, and covers nearly 93% of all users — Can I use "WebAssembly". This isn't the same plugin-based approach that Silverlight relied on. It's the future of the web, and you'll continue to see developers building applications using this technology.

🔒 Safe and secure

Wasm is every bit as secure as JavaScript.

"WebAssembly describes a memory-safe, sandboxed execution environment that may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same-origin and permissions security policies of the browser."

webassembly.org

In other words, Wasm is confined to play within the same security sandbox as JavaScript.

JavaScript security sandbox

✨ Web application platform

With modern web application development, you want your apps to be responsive on both desktop and mobile browsers. Modern web apps are much more sophisticated and rich in content than their predecessors, with feature expectations of real-time web functionality, progressive web app (PWA) capabilities, and beautifully orchestrated user interactions. For the first time, .NET developers can use their existing C# skills to build all sorts of apps on the web. In my opinion, this helps blur the lines between backend and frontend developers — but more broadly expands app development through the web. I believe the philosophy of using the same programming language on the client and server leads to more rapid adoption, and Node.js comes to mind specifically.

➕ Familiarity

It's easy to press upon the fact you can use your existing C# skills, but it's often an oversight not to call attention to the fact that there is still HTML, CSS, and JavaScript. In this way, you can keep using your HTML and CSS skills, your favorite CSS libraries, and you're free to work smoothly with existing JavaScript packages. After all, you're still building web apps!

🕓 Brief history

In the early days - back in 1996, Active Server Pages (ASP) offered the first server-side scripting language and engine for dynamic web pages from Microsoft. As .NET Framework evolved, ASP.NET was born, and with it — Web Forms emerged. Web Forms was (and still is) used by many that enjoy what .NET is capable of, and it allowed for server-side rendering of HTML.

Sometime later, ASP.NET Model View Controller (MVC) was introduced and it made Web Forms look sluggish. MVC brought ASP.NET developers closer to the metal. Suddenly, they had to understand the 3 pillars of the web; HTML, CSS, and JavaScript. In MVC, there was simply a closer alignment to web standards. MVC also added a different programming model, which was based on controllers and views. This helped to address some resistance from the developer community, where developers took notice that their development interactions with Web Forms weren't stateless — an illusion from the framework which contradicted the nature of HTTP.

ASP.NET Web API grew in popularity, and developers embraced the power of .NET. Web API started being accepted as the standard for building .NET-based HTTP services.

Eventually, leveraging the Razor view engine from MVC — Razor Pages took to the stage. Innovations from ASP.NET Core made a lot of this possible.

"ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-enabled, Internet-connected apps."

Microsoft docs: Introduction to ASP.NET Core

ASP.NET Core offers first-class citizenship to all of the fundamentals you'd expect in modern development such as (but not limited to), dependency injection, strongly-typed configurations, logging, globalization and localization, authentication, and hosting.

Razor Pages converged controllers and views into being a bit more logically cohesive, leaning more towards true components, and building on Web API infrastructure.

After Razor Pages came Blazor. The name "Blazor" is a play on words, combining Browser and Razor, because as developers' were good at naming things — am I right? 🤣 That's where we are today, in a world with Blazor and all of its capabilities. The first of its kind for .NET, a single-page application framework.

Single-Page Application (SPA)

Blazor is the only .NET-based SPA framework from Microsoft. There are many popular SPA frameworks including:

The primary differentiator is that these are all based on JavaScript, not Wasm.

Sometimes developers building applications with Blazor confuse the differences in the two hosting models. There are misconceptions that Blazor Server (server-side) is not a SPA. The server-side nature feels more like the previous non-SPA .NET web app frameworks. But let's look to the definition of a SPA:

"A single-page application (SPA) is a web application or website that interacts with the user by dynamically rewriting the current web page with new data from the web server, instead of the default method of a web browser loading entire new pages"

Wikipedia: Single-page applications

Regardless of the hosting model, Blazor satisfies this definition. With Blazor Server, the server exposes a SignalR hub with a specific Blazor protocol which is responsible for communicating updates to the document object model (DOM) in the client app in real-time. When there are differences (or deltas) in the DOM, the changes are reflected immediately.

In Blazor WebAssembly, when the client requests the app it is served up as a bit of HTML, CSS, and JavaScript — like all other web apps. The blazor.webassembly.js file bootstraps the app and starts loading .NET binaries which can be viewed coming over the wire in the browser's Network tab.

💜 Open source

It's developed in the open, as part of the ASP.NET Core GitHub repository.

GitHub logo dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.

I'm a huge proponent of open-source software development. To me, being able to openly see how a feature is architected, designed, and implemented is a game-changer. The ability to post issues, propose features, collaborate with the dev team and others, and create pull requests makes the software community-centric. This ultimately makes for a better product, without question!

♻ Code reuse

SPA developers have been fighting a losing battle for years, where web API endpoints define a payload in a certain shape — and the developer has to understand the shape of each endpoint, ideally mapping to a model on the client. This is a very tedious process and is error-prone. Blazor can alleviate that concern by sharing models from .NET Web APIs, with the Blazor client app.

💡 Entire .NET libraries can be shared, and consumed in both server-side and client-side scenarios. Making use of existing logic, functionality, and capabilities allows for developers to focus on innovating more as they're not required to re-invent the wheel.

🛠 Tooling

Productivity of the development team is always a major concern for application development of all kinds. The developer tools that exist are key to success, if your team fumbles about or struggles to get common programming tasks done — the entire project can fail. With Blazor development, you can use proven developer tooling such as:

Additionally, the .NET CLI comes to mind and has become a productivity powerhouse, with new (templating), build, restore, publish, run, test, pack, and migrate commands (to name a few) — you're likely to find success.

✔ All of this built with the most powerful and modern programming language in the world today, of course, my opinion on that matter being C#.

🌐 .NET APIs

As a developer with more than a decade of real-world web application development experience, I can safely say that I have reliably used .NET for enterprise development of production applications time and time again. The API surface area of .NET alone is massive, and as an ecosystem with third-party packages from NuGet what's not to love?

❔ Why does that matter?

I recently witnessed a .NET API being developed, from its inception to fruition — and the process I observed is very mature and well established.

Keep in mind this happens entirely in the open, for the public to see. It started with early discussions and then an idea emerged, this led to an official proposal in the form of a GitHub issue. The issue captured everything you'd expect for the proposal, the problem statement, use cases, example syntax, suggested API surface area, example usage, and even links to the comments from the original discussion and idea.

The proposal was discussed and hashed out, there was much bargaining, reasoning, and negotiation. Then came a draft which was finalized from a group of people who participated in the public API design review meeting. The official .NET API design review meeting follows a weekly schedule. As part of the review, notes are captured, GitHub labels applied, and a stamp of approval is given — and with that, the .NET API in question is codified as a snippet.

From there, the issue serves as a point of reference for pull requests that aim to satisfy the proposal. A developer takes the issue, implements the API, writes unit tests, and creates a pull request (PR). The PR undergoes review, and when it's merged the API has to be documented, communicated, breaking-changes captured/reported, promoted, shared, analyzed, and so on.

All of this, for a single .NET API and there are tens of thousands of .NET APIs 😲. You're in good hands, with the strength of all the .NET contributors holding you up. For more information, see the official API review process.

I asked a friend of mine who holds the .NET API near and dear to his heart for a few choice words on the subject:

"The .NET platform prides itself on having a great set of APIs that are very usable and make you extremely productive no matter what kind of application you're building. With Wasm, this power is now also available when you build browser-based applications using Blazor WebAssembly."

Immo Landwerth

🆘 Support

With all .NET products, there are various support policies in place. Understanding the lifecycles of releases, and their corresponding support policy is often a crucial consideration for development teams. For the most part, it's recommended to build production-ready applications targeting a Long Term Support (LTS) release of .NET. However, some companies and development teams choose to track Current (or even Preview) releases — they tend to migrate more aggressively. For more information, see the official .NET site for support details:

🤝 Developer community

I asked a few Blazor developer community friends for their thoughts, and offered to share them as a quote when asked "Why Blazor?":

Blazor's component model makes building apps a joy. It's simple to get going but offers lots of customization when you need it.

— Chris Sainty @chrissainty

I agree with Chris. There's much joy in developing apps that are simple and customizable.

.NET productivity. I can use my existing skills, workflow, tools, and previously written libraries. There's no npm or webpack, instead, I have the .NET stack and its ecosystem, which makes me super productive.

— Ed Charbeneau @edcharbeneau

I couldn't agree more with Ed. Productivity is a critical driving factor — and not having to write a lot of JavaScript certainly eases the pain of web development 😬.

The Blazor developer community is thriving:

🎉 Promising future

In addition to the amazing Blazor developer community, developer tooling, open-source ecosystem, and strong opinions from respected industry leaders, there's also an entire UI component movement from the leading component vendors whom of which are actively building out Blazor components (in alphabetical order):

✔ Customer stories

Whenever Microsoft has customers who are excited to share their stories, they speak for themselves — here are two Blazor success stories:

👀 Code

To quickly create a Blazor WebAssembly project, use the dotnet new blazorwasm .NET CLI command.

In the preceding command, we specified the name (-n) of the project, and that we didn't want a restore. If you're to open the Pages/Counter.razor file, you'll see some Razor code similar to the following:



@page "/counter"

<h1>Counter</h1>

<p>Current count: @_currentCount</p>

<button class="btn btn-primary"
        @onclick="IncrementCount">
     Click me
</button>

@code {
    private int _currentCount = 0;

    private void IncrementCount() =>
        ++ _currentCount;
}


Enter fullscreen mode Exit fullscreen mode

This is a simple counter page. It is considered a page rather than a component due to its @page directive, which specifies the page route of "/counter". Since this is based on the Razor view engine, it serves as a template — where you can reference C# code variables in the HTML. This also demonstrates the use of the @code { ... } directive, which lets you embed C# functionality directly within the template file. The _currentCount variable is private and scoped to the page, and incremented from the IncrementCount method. This method is called from on the clicking of the button and is bound via the @onclick event. As the _currentCount value increments, the changes are reflected immediately where they're bound. In this case, they are displayed within a <p> element as the "Current count".

The counter page is just a small example of what's possible, and there are plenty of amazing opportunities for you as a web developer. I'm hopeful that you'll consider .NET for your next web app development project.

🔚 Summary

There are many tools for you as a developer to choose from. With all developer decisions, when deciding whether or not to use a framework should be a team decision. Blazor is another tool and does not apply to all use cases — knowing when to use it is just as important as knowing how to. In this post, we discussed the "what" and the "why". The "how" already has plenty of coverage.

Please consider the additional resources:

🤓 I'm an O'Reilly Media author for my book, 📖 Learning Blazor: Build Single-Page Apps with WebAssembly and C#.

Top comments (29)

Collapse
 
shaijut profile image
Shaiju T • Edited

Nice writeup 😄, I think The only issue with Blazor is initial load speed. Other features are fine.

Collapse
 
ievangelist profile image
David Pine 🤓

Thank you @shaijut - Depending on the hosting model, initial loading speed can vary - that is true. With Blazor Wasm it's very similar to the initial page load speed of other SPAs, such as Angular and React. However, there are optimizations being built out to provide "assembly trimming", pre-rendering, compression, etc. It's only going to get better With Blazor Server, it's much faster. If this is the only issue you have, I'll take that as a success. 😬

Collapse
 
ryansolid profile image
Ryan Carniato

Have there been any more recent work on performance? I know it's been a WIP but I've never seen anything really benchmark as slow as Blazor WASM. Some WASM technology is starting to comparable to JavaScript for DOM rendering so I've been wondering if improvements been made.

Source: github.com/krausest/js-framework-b...
Current Results: krausest.github.io/js-framework-be...

Rust WASM is 4th(albeit with no framework abstraction, fastest Rust framework is like 30th), Blazor is 2nd to last.

Not that I have any attachment to Rust just that I've heard hype but everything I've seen suggests completely the opposite.

I was trying to profile the realworld demo about 6 months ago:
blazor-conduit.netlify.app/
And I got one of the highest scores I'd seen a 99. But then I realized it was because it took so long on the loading screen Chrome Lighthouse that it was done loading right at the start. Things have gotten better since then and I'm getting actual scores in the 30s.

While that is the official listing on codebase.show/projects/realworld I assume there are probably issues with it. Those 2 are just the place that people commonly go to look at JavaScript frameworks. Are there any better performance comparisons?

Thread Thread
 
csharpfritz profile image
Jeffrey T. Fritz

Both of the sample apps you link to were written more than a year ago and are not using current versions or even RTM versions of the framework.

Let’s update them to .NET 5 and perhaps even take a look at the numbers in a current .NET 6 preview to see how they perform

Thread Thread
 
ievangelist profile image
David Pine 🤓

I agree with Jeff Fritz, these are dated but to your point Ryan - we should do a better job of actively benchmarking the performance of things like DOM rendering, initial payload, and all of the metrics that Lighthouse offers (first contentful paint, time to interactive, total blocking time, speed index, etc.). I'll ask around, and can only assume that this is something that Steve Sanderson already has on his radar. Thank you

Collapse
 
stackundertow profile image
StackUndertow • Edited

It in no way shape or form even competes with load speed, first render, etc on those frameworks unless you have an incredibly poorly engineered TradSPA(tm).

But don't take my word for it, here's a near-hello-world James Newton-King put together on the latest recently for serialization testing that takes 8-13s to first contentful paint on a fast connection with low latency, even with brotli compression:

grpcblazorperf.azurewebsites.net/

For ref: That's 60s on fast 3g, with a whopping 23mb into cache (literally as much as youtube's landing page).

The other thing to note is that there's typically an ~1s gap between the completion of dotnet.wasm download and the actual page render, so the first render after a massive download is another 800-1000ms.

Our performance budget is application-related downloads need to be < 200ms on a 1mbps connection, and first contentful paint should be shortly after that (500ms).

Server side rendering: I can't share how I feel about "just throw a fleet of servers at it and it gets way faster," on this site. We're doing 1M requests/s with dotnet core apis on an EKS setup with just a few small nodes and an Angular application that meet our perf budget. All I see at build/etc is Blazor, blazor, blazor, but it's not a realistic option for anything at this point in time compared to tech that's already standard in the dotnet community.

Collapse
 
shahabfar profile image
Majid Shahabfar

This issue is mitigated in .NET 6

Collapse
 
wshaddix profile image
Wes Shaddix

What about cost? That doesn't get mentioned much in Blazor articles but when I checked, Blazor server requires SignalR for every single person who views your site (not just clicks buttons), which means you have to have capacity not just for how many people take action at the same time, but how many people actually visit your site at the same time.

According to Azure SignalR pricing, 1 unit can serve 1000 connections and costs approx $50/month. This charge is in addition to your web application plan which is also going to be a minimum of around $50/month. That is $100/month for 1000 visitors and an additional $50 per block of 1000 visitors.

As a startup, that seems like an expensive proposition. Can you speak to the real world cost of running a blazor server app? I love the tech, and it's great, but I'm concerned it may not be cost effective outside of an intranet site. Am I understanding the cost model correctly?

Collapse
 
ievangelist profile image
David Pine 🤓 • Edited

Hi Wes, this is a great point to bring up - I touched base with Daniel Roth on this. Here is what he said:

With Blazor Server you are using your server resources to handle running the UI for each user that uses your site. Basically your offloading work from the client to the server.

The pricing for Azure SignalR is based on concurrent users. That's important. You can have a lot more users per month, but they probably aren't all using the site at the same time.

If you don't want to take on this cost, the Blazor WebAssembly is the way to go. Blazor WebAssembly offloads the work down to the client. In fact, Blazor WebAssembly apps can be deployed as static sites. Azure Static Web Apps is a great serverless hosting solution for Blazor WebAssembly apps.

@danroth27

The choice is yours, and I can tell you that I'll be using Wasm over the server-side option. But I may still choose to add SignalR functionality for other aspects of my apps.

Collapse
 
seangwright profile image
Sean G. Wright

Blazer is awesome and glad it's brought a client side option to C# developers (F# devs have had some options for awhile with Fable).

I wish that the focus on Blazer didn't pull so much attention away from classic server side HTML generation with Razor. I feel like Tag Helpers and View Components won't get many enhancements now that everything is pushing Blazor as the solution.

The ASPNET team looks to the community for direction and the community is hyped on Blazor 🤷‍♂️

Collapse
 
ievangelist profile image
David Pine 🤓

This is an interesting observation. At the end of the day, the Razor view engine is shared - yes, that is true. But the way I see it, improvements made to it for Blazor will also be applied to other use cases where it is prevalent.

Collapse
 
seangwright profile image
Sean G. Wright

I would love for the Blazor component model and server-side rendering process to made available for traditional server-rendered HTML.

Web Forms did a lot of things that needed corrected once the web became a more robust platform, but it did have a really rich component model which MVC never got.

I feel like Tag Helpers and View Components could be expanded to do things like content projection and better composition. Since Blazor's rich component model already has these, it would be really cool to see them made available to apps that don't intend to ship all the Blazor bits to the browser.

Collapse
 
jwp profile image
John Peters • Edited

Blazor is a potential disrupter due to the power of C# and things like WASM, Security, LINQ, EF, Newtonsoft, Azure, VSCode and VS2022. Isomorphic from top to bottom. TypeScript falls inline as well.

The best eco system anywhere. My original Blazor skepticism has vaporized with just 2 days of use of VS2022.

I still am nervous about getting dumped like MSFT has done before, this time, hopefully; they are settling in on a single architecture for good. Their last repair work is to unify the desktop after 15 years of horrible direction.

Collapse
 
amsabuncu profile image
A. M. Sabuncu

Quality write-up, thanks.

Collapse
 
adomovic profile image
Michael Adom

Wow, great piece about Blazor.

Collapse
 
ievangelist profile image
David Pine 🤓

Thank you very much Michael!

Collapse
 
shahabfar profile image
Majid Shahabfar

Reduced Blazor WebAssembly download size with runtime relinking in a new feature in .NET 6 Preview 5

Collapse
 
keefdrive profile image
Keerthi

Nice article. The snippet of code for counter app looks similar way svelte components are written.

Collapse
 
ievangelist profile image
David Pine 🤓

Indeed, lots of the available SPA frameworks today are fairly consistent with how their templates handle binding.

Collapse
 
rjzauner profile image
RoryJZauner

Awesome article. Thank you!

I enjoyed using Blazor and it is a nice alternative to have alongside React and Vue.

Collapse
 
ievangelist profile image
David Pine 🤓

Thank you so much for your kind words. I happy you enjoyed it.

Collapse
 
yoshi88mx profile image
Emilio Yoshimar

Exelent, thank you

Collapse
 
ievangelist profile image
David Pine 🤓

You're very welcome, thank you Emilio.