Why we started this experiment

Last year Microsoft released the first version of Blazor. With Blazor, it is possible to write single-page web applications with .NET. If you are interested in an overview of Blazor and the different possibilities, you can read my Blazor introduction blog post.

Our customer, the Andritz AG is using .NET for internal applications, for many, many years and they have a lot of experience and know-how in this technology. But since there was no possibility at the time to write modern single-page applications with .NET, they chose Angular as their preferred technology for frontend development.

Because their internal resources are limited, we developed a small internal tool to monitor orders for them. Most of the work happens in the backend where data from different sources is aggregated. The UI offers a search and a detail-view with multiple lists that can be filtered and sorted. The backend is written in .NET Core and the frontend in Angular.

At Guid.New we love to work with cutting-edge technology and build modern applications. It’s important for us to get real-life experience with new technologies as soon as they arrive. This allows us the help our customers to make the right decisions for the future.

Since the Andritz AG has a .NET heavy development department and only little focus on Angular, the possibility to rely on one key technology for the whole system is very appealing. That’s why we decided to port the existing Angular application to Blazor. These are the questions we wanted to answer with this experiment:

  • How is the developer experience and can we re-use existing .NET knowledge?
  • How does the output compare between the Angular and Blazor application?
  • What are the differences between Blazor Server and Blazor WebAssembly and what should we use?
  • Is Blazor future-proof or will it be the next Silverlight?

Developer experience and re-using existing .NET knowledge

.NET exists for more than 10 years now and there is a large ecosystem of tools, libraries, blog posts, and documentation available. But since Blazor as a technology is very new, the question is, how it fits into the existing .NET ecosystem. Additionally we wanted to find out how hard it is for existing .NET developers to start building Blazor applications.

Tools and ecosystem

Starting with .NET Core, the .NET framework started to be a single framework for different platforms (Windows, Linux, macOS) and different purposes (Web Server, Desktop, Mobile). This transition will continue with .NET 5 and should be finally completed (for now) with .NET 6, coming next year.

Blazor is part of ASP.NET Core which means it shares the same tools like the SDK and CLI. Most of the tools that support ASP.NET Core and C# also support Blazor. This includes of course Visual Studio and Visual Studio Code.

We already used Visual Studio to develop the backend for the Order Monitoring project. For the Blazor frontend, we just added a few additional projects to our solution. Now we can code, build, and debug the whole project from within Visual Studio.

The continuous integration pipeline (we use Azure DevOps) was already configured to build the backend projects. Without any additional changes, now it also builds the Blazor projects and publishes the build artifacts.

The .NET framework gives us access to a lot of APIs already, but another key area is the support of 3rd party libraries. There are currently more than 220k packages on nuget.org available. Blazor is built on .NET Core 3.1 which means you can reference any package that targets .NET Standard or .NET Core. But keep in mind, not every package is meant to be added to a client-side web application, and not all APIs are supported in the browser sandbox.

In some cases, for example, for UI components, the libraries must be built specifically for Blazor. But most of the time, you can just use one of the already existing and long-tested packages.

In the Angular app, we incorporate some Telerik components, for example, the Grid component. I was surprised to see, that Telerik (and some other component vendors too) already offer support for their components for Blazor. So we utilised those Telerik components in our Blazor port too and they already worked very well. They are not feature-complete yet and definitely not comparable to the Angular version, but for our use-case, it was good enough. Also, the development of this project was at the beginning of this year, and since then, Telerik has already released many updates with new features and improvements.

A few more packages which we were already using for quite some time in our “normal” .NET applications, and were fully compatibly with our Blazor port are FlurlJson.NET, and StyleCop.Analyzers.

Blazor for .NET desktop developers

In Blazor applications, you write your code in C# and you describe the UI using the Razor syntax. When you are a .NET desktop developer using WPF or WinForms, then you will face a lot of differences. While the C# code is the same and you can use similar patterns like MVVM, ReactiveUI, or whatever you prefer, the UI part is very different. It is a browser application and that means you have to learn HTML and CSS and also deal with different behaviour in different browsers across different operating systems (although this is already a little less frustrating than a few years ago).

But compared to Angular, Blazor makes the move to web development much easier. Because for Angular, you also have to deal with Typescript, NPM, the Angular CLI and of course the Angular framework itself, in addition to HTML and CSS.

Blazor for .NET web developers

When you are already familiar with .NET web development, the switch to Blazor is much easier. You already know about all the pitfalls of HTML, CSS, and different browsers. And if you have used ASP.NET (Core) MVC in the past, you may also be already familiar with the Razor syntax.

Blazor is part of ASP.NET Core and uses the same foundation. If you know how to build ASP.NET Core web applications, you already know most of the things you need to know to build Blazor applications. Of course you will encounter some Blazor specifics here and there (like authentication and routing), but they are easy to figure out, when you already understand how ASP.NET Core works.

If you are an ASP.NET Web Forms developer, then you will find many similarities between Web Forms and Blazor. To make the transition for you easier, I can recommend you the free e-book from Microsoft, Blazor for ASP.NET Web Forms Developers.

Challenges

Using a brand-new technology comes not without its challenges. For example, in our tests, the debugging experience of Blazor WebAssembly is on par with the debugging of other .NET or Angular projects.

For Angular, you can find many best practices to build enterprise applications. How to structure your code, how to manage the state, and so on. There are nearly no resources available for Blazor yet. And there are no broadly recommended libraries available for specific topics, like ngrx for state-management in Angular.

In Blazor, you use only C# and Razor to write your code, but in some cases, it is still required to use JavaScript. You can use JS interop to execute JavaScript or call a method of a script file that was loaded with the page. Usually, you will use a component library that does all this for you. But be prepared to work with JavaScript in some situations.

One more thing that could be improved, is working with styles and assets. In Angular, you get all this webpack magic. It compiles SASS files to CSS, it optimises the size, bundles the output, and adds hashes to the file names for cache-busting. In our project, we used the WebCompiler Visual Studio extension.

Comparing the output

We gave you an impression on how it was for us to build a real-life application with Blazor, now we also want to compare the outcome of our Blazor prototype with the existing Angular application. Will the users notice any difference?

Bundle Size

The first thing you can compare when you start a web app is the download size. When we navigate to an URL for the first time, the browser has to download an initial HTML page, the application code, and other resources like styles, fonts, and images. I will compare only the application code because the other things are more or less the same in the Angular and Blazor applications.

For the Angular app, the size of the JavaScript files transferred over the network is 775kB. This is a production bundle created with the Angular CLI and it contains our code, the Angular framework, and the 3rd party libraries with have used.

On the other hand, the Blazor WebAssembly app transfers only 395kB of JavaScript code. Most of the JavaScript code is from the Telerik Blazor library (~300kB). But in addition to the JavaScript, the Blazor app also loads the .NET runtime in WebAssembly format (622kB) and all the framework DLLs, 3rd party DLLs, and our DLLs (together ~3MB).

This means for the Angular app we must load ~0.8MB and for the Blazor app ~4MB, which is a huge difference. The reason for that, is that JavaScript was always meant to be used in the browser and therefore is optimised for small download size. Over the years additional tools and techniques (like tree shaking) were introduced which further reduced the bundle size. Unlike, .NET which was mainly used in desktop applications or web applications running on a server, where the size was never really a thing.

To make it possible to reduce the size of the Blazor WebAssembly app, the Intermediate Language (IL) Linker is used to trim unnecessary IL from the apps output assemblies. It works similar to tree-shaking in JavaScript. The linker is enabled by default only in release builds. The usage of reflection makes it hard for the linker to find out what is used at build time. That is the reason why there are additional features available in .NET 5 to improve the linker and further reduce the output size. In the first quarter next year (early previews of .NET 6), there will also be ahead-of-time (AoT) compilation. Currently, only the runtime is compiled to WebAssembly. With AoT, it will be possible to also compile the framework assemblies and our code to WebAssembly. This will further reduce the bundle size and improve the performance at runtime.

In the end, you must decide from project to project how important the bundle size is. In our case, the application is used only by a small number of users and on desktop PCs only. The bundle size does not really matter in this scenario. And, if you do not ship daily updates, the browser caches the resources and there is nothing to download when you access the page again.

Blazor Server is not comparable to Angular and Blazor WebAssembly regarding bundle size. It loads only a small script (76kB) that opens the WebSocket connection and updates the UI.

Performance

Next, we did compare startup- and runtime-performance.

While most of the time Blazor is pretty fast, when you try to make a lot of changes in the UI, like loading a long list of data, then it can get very slow. In Blazor WebAssembly I had multiple situations where the browser got unresponsive for a minute or so.

In Blazor Server it can also take some time to load long lists of data. But the long loading time is not the only problem. While the messages with UI updates from the server are usually very small, for long lists we noticed that they can get very large. In a test with a list of 5k items, the message had ~10MB. In comparison, the JSON with the same data had only a few hundred kilobytes.

Techniques like pagination and virtual scrolling can prevent such issues.

Blazor Server vs. WebAssembly

Before you start your new Blazor project, you must decide if you want to use Blazor Server or Blazor WebAssembly. As we had no practical experience at that time, we decided to try both variants and compare them. But is it possible to share code between those two? And are there any noticeable differences?

Code sharing

My first goal was to get both variants up and running asap without spending too much time on thinking about how to share code in-between them. Blazor WebAssembly was more interesting for me, so I decided to start with port of the Angular app to Blazor WebAssembly first. I was able to re-use the existing web API which we were already using in the Angular app.

When I started with the Blazor Server implementation, I created a new project and copied all the code, images, styles, etc. from the Blazor WebAssembly project to the new Blazor Server project.

Only then I have created a shared project and started to move the duplicate code file by file. In the end, it turned out that it was possible to move almost everything to the shared project. All razor components, images, styles, and fonts could easily be reused.

The code that specific to the authentication cannot be shared. That is, because in Blazor Server we were using cookie authentication while Blazor WebAssembly was using bearer tokens. And the service implementations to load data cannot be shared neither. On the server, we are loading the data from the database while on the client, we are loading it via the web API.

If you do not want to decide yet what version to use or you just want the flexibility to easily switch later, there is not a lot of additional effort necessary to support both at the same time.

Comparison

Even though we use the same code to build Blazor Server and Blazor WebAssembly apps, they are executed in completely different ways.

Blazor Server uses a stateful model and the .NET code runs on the server. The browser loads only a very small script that opens a WebSocket connection to the server. All client-side events get sent to the server and the server sends the UI updates to the client. All the processing and state management happens on the server. This requires a constant internet connection.

With Blazor WebAssembly, the code is executed in the browser. Once the app is loaded you can use it, even without an internet connection. Blazor WebAssembly is comparable to Angular and other single-page web application frameworks.

In the Order Monitoring project, it is all about working with live data from the server. Therefore, an active internet connection is required in any case to use the app. This limitation of Blazor Server was no problem for our use case and probably isn’t a problem for many other similar apps neither.

As mentioned before Blazor Server feels a bit faster and more responsive than Blazor WebAssembly. Besides that, we didn’t notice any big differences when using the app.

Blazor vs. Silverlight

When you hear .NET in the browser, you may remember Silverlight. Silverlight was a compact, cross-platform version of the .NET framework. With a browser plugin, it was also possible to run apps written in C# and XAML in the browser. The .NET APIs of Silverlight were limited in comparison to the full .NET framework and the Silverlight XAML was not fully compatible with the WPF XAML.

In comparison, Blazor does not require any browser plugin. Blazor WebAssembly uses only open web standards to execute the .NET code in the browser. And with Blazor Server the .NET code runs on the server and the communication between client and server is done via a standard WebSocket connection.

Blazor is also neither a separate framework nor is it a completely new technology. It is part of ASP.NET Core and uses the same foundation, the same SDK, CLI, BCL, etc. And, like .NET Core and ASP.NET Core, Blazor is completely open-source.

Conclusion

Blazor is a new way to write single-page web applications with .NET. But while Blazor is new, it is built on top of ASP.NET Core which allows us to use a lot of the existing ecosystem of tools, resources, and NuGet packages. It reduces the barriers for .NET developers to get into client-side web development.

We have also learned that it is not necessary to decide upfront if we want to use Blazor Server or WebAssembly. With little effort, it’s possible to support both while sharing most of the code.

Whether Blazor is the right choice for your next project depends on your skillset and the use-case of the project. If you already have .NET web development experience and you want to develop a small to midsize project, you can definitely give it a try.

All in all, Blazor is an exciting technology and I am looking forward to what is coming next. If you want to start a Blazor project and need support or if you need a Blazor training, let us know – we are here to assist.