We are not gonna talk here why we should forget JavaScript as a nightmare because it's obvious! Just take a look at this code and tell me what will be the result:

[] + [] = 
{} + [] = 
[] + {} =

You can find answers in this amazing talk called "Wat"

Time to Forget JS

Fortunately, with the creation of WebAssembly, we can use other languages to write web applications. You can compile your C, C++, or Rust source code to WebAssembly byte code and run it in the browser. As the next step in web development, engineers from Microsoft have compiled mono runtime to WebAssembly and ASP.NET Core Team is now working on an amazing framework called Blazor. This platform gives you the possibility to write component-based web applications using C# and VisualStudio (VS Code is also supported).

Finally, no more stupid runtime errors because you are using an object of the wrong type (we all love C# for static typing). We can finally share code (assemblies) between client and server. You can define enums, validation logic, some business rules, etc. once and use them everywhere. And of course, it's gonna be the same language across the whole system.

To be clear, there are two "hosting models" for Blazor, client-side (runs in the browser on a WebAssembly-based .NET runtime) and server-side (runs on the backend, the client will get HTML and will interact with the server using SignalR).

blazor-hosting-models

In this article, I'm gonna talk about client-side Blazor. But the main concepts, the app and component models, are the same.

Component Architecture

As you can see from the image, on top of .NET runtime we have boxes called "Razor Components". What is Razor Component?

A component is an element of UI, such as a page, dialog, form, or even a button that defines rendering logic, can react to user events, and can be nested and reused. It's written in Razor markup (mix of HTML and C#)  and has .razor file extension. Here is an example of dialog (Dialog.razor, from official documentation):

<div>
    <h1>@Title</h1>

    @ChildContent

    <button @onclick="@OnYes">Yes!</button>
</div>

@code {
    [Parameter]
    private string Title { get; set; }

    [Parameter]
    private RenderFragment ChildContent { get; set; }

    private void OnYes()
    {
        Console.WriteLine("Write to the console in C#! 'Yes' button was selected.");
    }
}

Now you can use this component in other parts of your application and define your own content via ChildContent and Title properties. Let's see it how we do that in Index.razor):

@page "/"

<h1>Hello, world!</h1>

Welcome to your ivanderevianko.com

<Dialog Title="Blazor">
    Do you want to <i>learn more</i> about Blazor? Then go to the <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/">official documentation.</a>
</Dialog>

This example also shows us one of the ways we can define routing in the app. You just use @page directive and pass the relative path to the page.

JavaScript Interop

If you want to access Browser APIs (e.g. local storage, history, etc.) or use your favorite JS library in the component, you can easily interoperate with JavaScript. Components can call JS code, and JavaScript code can call into C#.

Browser Support

Since WebAssembly is working in four major browsers, latest versions of Edge, Firefox, Chrome (including Android), and Safari (including iOS) are supported by client-side Blazor.

Awesome! Can I have two?

Unfortunately, Blazor is still in preview and there are some rough edges.

It is slow in number crunching, even though rendering is quite fast if you compare some basic operations to JS you will see 20 to 100 times slowdown. This is because mono runtime is running on WebAssemble, so basically one virtual machine is running inside another.

we need to go deeper

ASP.NET team is working on Ahead of Time (AOT) compilation for Blazor, so instead of compiling C# to IL, it will be compiled directly to WebAssembly bytecode.

As well, the size of the bundle is quite big. You need to download around 2.6 MB of data when you load application for the first time. Of course it gets cached in the browser, but still, 2.6 MB is quite a lot for an empty app. It should be better if you use: /p:PublishTrimmed=true switch while publishing.

There is no live reload yet, so if you change anything in your component you need to rebuild it and then reload the page.

Client-side Blazor will not be released until the .NET 5, and server-side Blazor will be available as part of .NET Core 3.0 release. Let's see what it brings us!