Blazor.Cordova
I’m sure most of you have heard of Blazor at this point. If you haven’t, take a look at my other Blog post where I take a quick look at Blazor.
What’s the reason to run Blazor inside a cordova app?
Blazor makes it easy to create UI that works on all platforms. You might also want to take an existing Blazor app and run it as a mobile app with all the benefits that come with that.
With JS-Interop it would also be possible to use native device functionalities right from within your blazor app.
Ok you got me hooked how do I do it?
Cordovas browser is based on chromium and supports WebAssembly. Blazor compiles down to static files so it should actually be pretty straight forward right?
So let’s try it.
First let’s create a new Blazor and cordova project from the command line.
$ dotnet new blazor -o blazor
$ cordova create blazor-cordova
Now lets create the static files we need for our cordova app by running
$ dotnet publish -c Release -o ../Output blazor/blazor.csproj
Now lets copy the files from Output/blazor/dist
into the www
folder of the cordova project.
All that’s left to do, is add the platform to our cordova app and run it.
$ cordova platform add android
$ cordova run
And…
The app is stuck at the loading screen. So what now?
Let’s take a look at what’s going on in the developer console.
Fixing the path problem
It looks like our files are not loading. Probably a problem with absolute paths. So let’s remove the following line from index.html:
And now?
That’s weird. Some of our files could be loaded, but the blazor.webassembly.js still couldn’t be found.
After doing some research you’ll find out that android omits files and folders starting with an underscore.
We’ll have to modify blazor to change the folder names during build. So let’s do that.
Create a file called Blazor.Cordova.props
and paste in the following content.
Now we need to add a reference to this file for it to get used during build. Add the following line to the blazor.csproj file.
Great! So now if we build the project, all the framework files will be put into the framework directory without an underscore.
Because of that we also need to modify index.html to reference the right path.
So what happens if we run it now?
That’s unfortunate. Looks like blazor.webassembly.js is trying to load another file using the javascript fetch api. The problem is that the fetch api doesn’t support loading local files.
Using XMLHttpRequest
One way to fix this is to override the browsers fetch api with our own implementation using XMLHttpRequest.
So let’s add the following to index.html before any other script imports.
Great! Now our requests are working.
Event more path problems
The problem is that the paths inside the blazor Javascript files are hardcoded to use_framework
.
To fix this, add the following to the csproj file.
After that our output looks like this.
Fix WebAssembly loading
Looking at the source of mono.js we see the following:
This means we have a problem. The mono.js file is trying to use WebAssembly.instantiateStreaming
, which of course doesn't work with our overridden fetch api.
In order for it to not use the instantiateStreaming feature, we need to add the following line to the previously created script in index.html
We also need to modify the rest of the script a bit so that we can return the binary data:
This looks like another path problem. Luckily we already know how to fix those. So let’s modify our csproj file.
Home stretch
THIS LOOKS GREAT!
This means our runtime and application was loaded and is running. Now all that’s left to do is modify the initial route in our application to match /index.html
.
For that just modify the first line in Paged/Index.cshtml
to:
ET VOILÀ
Now we have a working blazor program inside a cordova application.
Sources
If you want to take a look at the finished sources for this project head on over to github. https://github.com/BickelLukas/Blazor.Cordova
NuGet Package
If you want to get started with using Blazor inside a cordova app, you can use the Nuget package I created.
The package does exactly what I described in this post but without all the manual grunt work.
You can find it and instructions on how to use it at https://github.com/BickelLukas/Blazor.Cordova