DEV Community

Cover image for How to create a Blazor app for WASM, Windows, Linux, macOS, iOS, Android
Urban
Urban

Posted on

How to create a Blazor app for WASM, Windows, Linux, macOS, iOS, Android

Hey everyone!

I got a few messages asking me how I created my free, open source habit tracker app OpenHabitTracker so I decided to write a post about it.

You can see the source code on GitHub.

Why Blazor

I wanted to create an app that would work on as many platforms as possible and share as much code as possible between all platforms.

I compared all cross platform C# frameworks that were available:

Framework First Release UI Technology Windows macOS Linux Android iOS Web (WASM)
.NET MAUI May 2022 XAML Yes Yes No Yes Yes No
Blazor Sep 2019 HTML + CSS Yes Yes Yes Yes Yes Yes
Avalonia Feb 2015 XAML Yes Yes Yes Yes Yes Experimental
Uno Platform Sep 2018 XAML Yes Yes Yes Yes Yes Yes
Xamarin.Forms May 2014 XAML Yes No No Yes Yes No

Xamarin was replaced by MAUI and MAUI doesn't support Web - that left Avalonia (with poor web support at that time), Uno and Blazor.

I have used a few open sourced project managed by volunteers and it did not have the best experience, so I wanted to choose a project backed by a company.

I was working with WPF for 5 years and in that time I found out that I really don't like XAML, so I was really happy when Blazor came out.

My first Blazor project was only with WASM and Windows through WebView2 in WinForms / WPF. When Maui Blazor Hybrid was announced I knew that Blazor was a good choice.

How I started

I started by creating a project from every Visual Studio Blazor project template in a single solution and then I started to move all the files that were the same into a shared library.

At first, I had only a single shared library, but later I split it into OpenHabitTracker of type <Project Sdk="Microsoft.NET.Sdk"> that holds the core classes and to OpenHabitTracker.Blazor of type <Project Sdk="Microsoft.NET.Sdk.Razor"> that holds the razor files. This way the logic is separated from the UI and the razor files contain few lines of C# code which is a good thing because Visual Studio editor for razor files can behave strangely at times, especially with @code blocks. The editor behaves better if you have your C# code in .razor.cs code behind files, but you can just go one step further and have the C# code in a separate library.

At first, I had only my razor components and razor pages in the shared library, I didn't move App.razor, _Imports.razor, MainLayout.razor, JsInterop.cs, jsInterop.js, app.css into the shared library, but later I figured out that you can move all files except Program.cs and index.html into the shared library - if there is any platform specific behavior, you can solve it with C# interfaces - even if you need platform specific razor UI, you can still solve it with interfaces and methods that return a RenderFragment. All .css and .js files can be in the shared library and then included to platform specific projects in index.html with _content/OpenHabitTracker.Blazor/... for example <link rel="stylesheet" href="_content/OpenHabitTracker.Blazor/app.css" />.

How I chose the frameworks

I started comparing all the frameworks that support Blazor on desktop and mobile:

Windows only:

  • WPF: works great with Microsoft.AspNetCore.Components.WebView.Wpf NuGet
  • WinForms: works great with Microsoft.AspNetCore.Components.WebView.WindowsForms NuGet

Windows, Linux, macOS:

  • Photino Blazor: works great with Photino.Blazor NuGet
  • Electron.NET: works with ElectronNET.API NuGet - long compile times, very large builds, slow startup, opens the GUI window AND a terminal
  • Chromely: works with Chromely NuGet - long compile times, slow startup, opens the GUI window AND a terminal - GitHub repo was archived by the owner on Jan 16, 2023

Windows, macOS, iOS, Android:

To support WASM, Windows, Linux, macOS, iOS, Android you need at least:

  • Blazor WASM
  • Maui
  • Photino Blazor

I develop on Windows with Visual Studio 2022 and my startup project is usually OpenHabitTracker.Blazor.Photino because it compiles and starts much faster than OpenHabitTracker.Blazor.Wasm or OpenHabitTracker.Blazor.Maui.

Saving user data

I took a look at the different options for storing user data:

Technology Size Limit Data Lifetime Storage Format Security
Cookies ~4 KB Configurable String HttpOnly, Secure
Session Storage 5-10 MB Session-based String Isolated to tab
Local Storage 5-10 MB Persistent String Shared across tabs
WebSQL 5 MB+ Persistent Relational DB Deprecated
IndexedDB Hundreds of MB Persistent Key-Value (Objects) Same-origin
Cache Storage (SW) Large Configurable HTTP responses Origin-bound
File System Access API Device-dependent Persistent Files/Blobs Requires Permission

Because I wanted a large, persistent storage that does not require prompting the user for permission and is not deprecated I chose IndexedDB:

I made two mistakes:

  • I chose Reshiru.Blazor.IndexedDB.Framework and I even fixed a few things and created https://github.com/Jinjinov/IndexedDB.Blazor (don't use it, it has the same problem)
  • I used IndexedDB on desktop and mobile - it works, but I think SQLite is a better option.

I switched to DnetIndexedDb for the browser and to EF Core + SQLite for desktop and mobile.

The user interface

At first, I wanted to write all CSS on my own, but I soon realized that using Bootstrap is not that bad and saves you a lot of time.
That proved to be a good decision when I decided to implement themes and discovered that Bootswatch offers 26 themes for Bootstrap.

I decided to use a free UI library, so I took a look at what was available:

Library Features First Release
Blazorise Bootstrap, Bulma, AntDesign, Material June 2019
MudBlazor Material Design components April 2020
AntDesign Blazor Inspired by Ant Design March 2020
MatBlazor Material Design components February 2019
BlazorStrap Based on Bootstrap 4/5 April 2019
Blazor Bootstrap Bootstrap 5 components June 2021

In my previous Blazor project, I used the Blazorise UI library because it had the most controls at the time and because it abstracts the CSS to C# enums and classes - that way it was really easy to switch from Bootstrap 4 to Bootstrap 5. The owner of the project is really responsive to ideas and requests (if you are reasonable and show some initiative). Later I found out that I don't actually need any complex components in my project, so now I use only Bootstrap 5.

In my previous Blazor project, I used Font Awesome icons and Google Fonts, but now I use embedded font files and Bootstrap Icons because I think they work better with Bootstrap 5.

In my previous Blazor project, I used CDN to get the CSS, JS and fonts from the web, but I found out that this makes the app noticeably slower. Now I include all CSS, JS and fonts into the project and the app is much faster. The app is around 2 MB larger because of all the included resources, but at 20 MB for the whole app that is only 10% more - for a much faster UI.

Feel free to ask any questions! :)

Top comments (0)