What is Blazor?

Blazor is an experimental project. It changes frequently and evolves rapidly. Therefore, it is possible that some content on this website is already outdated.

WebAssembly Changes the Game

In the past, JavaScript had a monopoly in client-side web development. As developers, we had the choice of frameworks (e.g. Angular, React, etc.) but at the end it always boiled down to JavaScript. WebAssembly changes that.

It is a low-level assembly-like language with a compact binary format that provides a way to run code written in multiple languages on the web at near native speed.

Covering WebAssembly in details is out-of-scope of this website. If you want to learn more, here are some important links to additional material:

WebAssembly and C#

JavaScript is a powerful language but it has its disadvantages. Some are fixed by TypeScript. However, using C# for client-side web development is compelling for many people because of reasons like the following:

  • C# is a very robust and feature-rich language that has proven to be successful for projects and teams of all sizes
  • Existing C# code could be re-used
  • ASP.NET Core is a powerful programming framework for server-side web development. Enabling C# on the client would allow teams to use a common technology stack on server and client.

Mono is an open source implementation of Microsoft’s .NET Framework based on the ECMA standards for C# and the Common Language Runtime (CLR). In 2017, the Mono-team has published first results of their attempts to bring Mono - and with it C#, the CLR, and the .NET Framework - to WebAssembly.

At the time of writing, Mono’s C runtime is compiled into WebAssembly, and then Mono’s IL interpreter is used to run managed code.

A prototype for statically compiling managed code into one .wasm file already exists. It is possible, if not likely, that Blazor will move away from interpreting IL towards the statically compiled model over time.

The following images illustrates the overall architecture of Blazor.

Blazor Architecture

The following images illustrates the boot process of a Blazor app in Chrome. The app (counter) includes Blazor’s JavaScript (blazor.js). It uses Mono’s JavaScript library (mono.js) to bootstrap the Mono runtime (mono.wasm) in WebAssembly. It then loads the app’s DLL (WebApplication2.dll) and the DLLs of the .NET Framework.

Loading Blazor app in Chrome

Blazor uses Mono’s IL Linker to reduce the size of your app. You see the IL Linker in action by looking at the Output window during build:

1>------ Build started: Project: RouterDemo, Configuration: Debug Any CPU ------
1>You are working with a preview version of the .NET Core SDK. You can define the SDK version via a global.json file in the current project. More at https://docs.microsoft.com/en-us/dotnet/core/tools/global-json
1>RouterDemo -> C:\Code\GitHub\learn-blazor\samples\RouterDemo\bin\Debug\netstandard2.0\RouterDemo.dll
1>Processing embedded resource linker descriptor: mscorlib.xml
1>Output action:     Link assembly: RouterDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
1>Output action:     Copy assembly: System.Text.Encodings.Web, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
...
1>Output action:   Delete assembly: System.Data, Version=2.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
1>Output action:     Link assembly: System.Diagnostics.StackTrace, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
1>Output action:   Delete assembly: System.Drawing, Version=2.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
...
1>Blazor Build result -> 28 files in C:\Code\GitHub\learn-blazor\samples\RouterDemo\bin\Debug\netstandard2.0\dist
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

As you can see, Blazor is not just a new Silverlight. The biggest difference is that it does not require a plugin. You will learn about other differences later.

Razor

Razor is a template engine that combines C# with HTML to create dynamic web content.

Razor has its roots on the server where it is typically used to dynamically generate HTML. In Blazor, Razor is used on the client. To be more specific, the Razor engine runs during compilation to generate C# Code from Razor templates.

The following image illustrates the process. On the right side, you see the Razor template. On the left side, you see the C# code that is generated from this template.

Razor template compilation

HTML Output

Overview

Unlike former platforms like Silverlight, it does not bring its own rendering engine to paint pixels on the screen.

Blazor uses the Browser’s DOM to display data.

However, the C# code running in WebAssembly cannot access the DOM directly. It has to go through JavaScript. At the time of writing, the process works like this:

sequenceDiagram participant CSharp participant JavaScript participant DOM CSharp->>JavaScript: Render Tree JavaScript->>DOM: Change DOM Note left of DOM: User triggers event (e.g. click) JavaScript->>CSharp: Event Note left of CSharp: Process event CSharp->>JavaScript: UI differences JavaScript->>DOM: Change DOM
  1. The C#-part of Blazor creates a Render Tree which is a tree of UI items.

  2. The render tree is passed from WebAssembly to the Rendering in the JavaScript-part of Blazor. It executes the corresponding DOM changes.

  3. Whenever the user interacts with the DOM (e.g. mouse click, enter text, etc.), the JavaScript-part of Blazor dispatches an event to C#.

  4. The event is processed by the C#-code of the web app.

  5. If the DOM changes, a Render Batch with all the UI tree differences (not the entire UI tree) is built in C# and given to a JavaScript Blazor method that applies the DOM changes.

Because Blazor is using the regular browser DOM, all usual DOM mechanisms including CSS work keep working.

Renderer

In Blazor, renderers (classes derived from the abstract class Microsoft.AspNetCore.Blazor.Rendering.Renderer, see source on GitHub) provide mechanisms for rendering hierarchies of components (classes implementing Microsoft.AspNetCore.Blazor.Components.IComponent, see source on GitHub), dispatching events to them, and notifying when the user interface is being updated.

For running in the browser, Blazor comes with a browser renderer (Microsoft.AspNetCore.Blazor.Browser.Rendering.BrowserRenderer, see source on GitHub).

For unit tests, Blazor currently uses a test renderer (Microsoft.AspNetCore.Blazor.Test.Helpers, see source on GitHub)