Special Offer: My C#/.NET Bootcamp Course is out now. Get 10% OFF using the code FRIENDS10.

Blazor Server and Blazor WebAssembly share many similarities but also have significant differences.

I will share five differences that impact deciding whether to use Blazor Server or Blazor WebAssembly for your next project.

Of course, Blazor Server runs on the server, and Blazor WebAssembly runs on WebAssembly in the browser. However, the five differences I will share go further than that and are more hands-on.

If you are new to the Blazor world, it will give you a great introduction from a different angle.

As a bonus, I will share one of the best similarities between Blazor Server and Blazor WebAssembly at the end of the video.

Project Structure (3 vs. 1 Projects)

The project structure is the first important difference between Blazor Server and Blazor WebAssembly.

Consider this example. I implemented a todo list app with Blazor Server on the left and Blazor WebAssembly on the right.

Project Structure: 1 Project for Blazor Server vs. 3 projects for Blazor WebAssembly

Notice the different number of projects. 

We have a single project in the Blazor Server application. It contains the Blazor components, the services accessing the data, and all data objects.

In the Blazor WebAssembly application, we have three projects. The Client project contains the Blazor components. The Server project contains the services and, additionally, an API layer to make the services available to the client over an HTTP connection. The Shared project contains data objects that are used in both the Client and the Server projects.

The project structure of a Blazor Server application is a lot simpler. You can access all the resources within a single project because all the code runs on the server.

API vs. No-Api

The first difference takes us to the second difference between Blazor Server and Blazor WebAssembly.

A Blazor Server project does not have an API layer. 

However, for Blazor WebAssembly, you have to implement an API. Even if the web application is the only API consumer, you still have to implement it. For example, to keep secrets such as DB connection strings on the server.

If you have a Blazor Server application, you can still share code. Nobody prevents you from sharing code using a class library

You can, for example, extract one or more services into a class library and use it in different Blazor Server applications. You can, but you don’t need to have multiple projects.

Scaleability vs. Simplicity

The third difference is scaleability versus simplicity. 

A Blazor WebAssembly application downloads to the client and executes client-side. It only connects to the server when fetching or sending data over HTTP. 

It puts less pressure on the server, which makes it simpler to scale. Besides running on a bigger server, you can also scale out and have multiple API servers behind a load balancer.

A Blazor WebAssembly application can be served from any web server.

For a Blazor Server application, we have a persistent web socket connection using SignalR between the client and the server. The server has to be running an ASP.NET Core application.

However, since no WebAssembly is involved, a Blazor Server application runs on all browsers and devices because it only uses HTML, CSS, and JavaScript on the client.

Scaling a Blazor Server application is simple when you add more resources to the same server. However, scaling out (adding more servers) will be a bigger challenge since all clients must always be connected to the same server.

We can also say that Blazor WebAssembly applications run stateless while Blazor Server applications are stateful. The server manages the state for all connected clients.

Same Objects vs. Different Objects in Services

Another difference to remember is whether we can use the same objects in Blazor components and services.

I can show you an example. We render all todo items in the Index component. We also have a button that the user can click to delete a todo item.

In the Blazor Server application, we inject the TodoService and provide the instance of the TodoItem. In the TodoService, we can use the object to find it and remove it from the collection.

namespace TodoAppBlazorServer.Services;

public class TodoService : ITodoService
{
    private readonly IList<TodoItem> _todoItems;

    public TodoService()
    {
        _todoItems = new List<TodoItem> {
            new TodoItem("Wash Clothes"),
            new TodoItem("Clean Desk")
        };
    }

    public void Delete(TodoItem item)
    {
        _todoItems.Remove(item);
    }
}

In the Blazor WebAssembly application, we call an API to delete the todo item and provide an id or, in this case, the text of the todo item. 

Index.razor:

@code {
    public async void DeleteItem(TodoItem item)
    {
        await Http.DeleteAsync($"Todo/{item.Text}");
        ItemsChanged();
    }
}

On the server, we call the TodoService in the TodoController and provide the text. In the TodoService, we need to find the correct todo item from the collection by its id or text.

TodoController.cs:

using Microsoft.AspNetCore.Mvc;
using TodoAppBlazorWebAssembly.Server.Services;

namespace TodoAppBlazorWebAssembly.Server.Controllers;

[ApiController]
[Route("[Controller]")]
public class TodoController : ControllerBase
{
    private readonly ITodoService _todoService;

    public TodoController(ITodoService todoService)
    {
        _todoService = todoService;
    }

    [HttpDelete("{text}")]
    public void Delete(string text)
    {
        _todoService.Delete(text);
    }
}

TodoService.cs:

namespace TodoAppBlazorWebAssembly.Server.Services;

public class TodoService : ITodoService
{
    private readonly IList<TodoItem> _items;

    public TodoService()
    {
        _items = new List<TodoItem> {
            new TodoItem("Wash Clothes"),
            new TodoItem("Clean Desk")
        };
    }

    public void Delete(string text)
    {
        var item = _items.Single(x => x.Text == text);
        _items.Remove(item);
    }
}

When using Blazor Server, we have all the data and context that we need. 

When using Blazor WebAssembly, we usually have to reload data from the database for every stateless call. Of course, you can use caching, but that introduces another level of complexity.

First Load Performance

When using Blazor Server, the application loads very fast. It only has to download the Blazor JavaScript bundle and render the first page. The size of the initial download remains the same, no matter how big your application grows.

When using Blazor WebAssembly, the whole application will be downloaded on the initial load. Depending on the size of the application, it can take a few seconds to load. Also, the size of the application grows over time when more and more features are added.

When I start my tiny todo app, Blazor Server is faster, but the WebAssembly version also loads quickly.

If your app mostly runs on mobile devices, Blazor Server might be noticeably faster for the initial load.

Bonus: 1 Similarity: The Blazor Component Model

Finally, it’s time for the bonus.

I talked about so many small and big differences between Blazor Server and Blazor WebAssembly. 

We must not forget the biggest advantage of Blazor. We can use the same component model for both Blazor Server and Blazor WebAssembly.

The component model is simple and allows for fast development. If you implement the services and components correctly, it’s very simple to migrate a Blazor component from one model to the other.

Conclusion

So, what do we learn from all of this?

For simple internal applications, I prefer Blazor Server

You have a good understanding of how many users the application will have simultaneously. The programming model is simpler. It’s less code, and the code is simpler as well. You have fewer data reloading and no forced API layer.

If you want to build a public-facing application that will be used by thousands or tens of thousands of users simultaneously, Blazor Server might hit its limits. You will run into scaling issues that are simpler to solve using Blazor WebAssembly.

Also, suppose your application doesn’t need to call the server for every operation, for example, because a lot of the logic can be included in the application. In that case, you have less network traffic, making it work better in case of bad network connection or offline scenarios.

The best thing about working with Blazor is that both hosting models share many similarities making it easy to learn developing for both models. Also, you can migrate an application from Blazor Server to Blazor WebAssembly or the other way with a reasonable effort.

I’m curious about your reasons for choosing Blazor Server or Blazor WebAssembly. If I have missed any important differences, please let me know in the comments.

If you learned anything here, subscribe to my YouTube channel to learn more about .NET development, and I will see you in the next video or the next article.

 

Claudio Bernasconi

I'm an enthusiastic Software Engineer with a passion for teaching .NET development on YouTube, writing articles about my journey on my blog, and making people smile.