Skip to content

Web DOM with Web Assembly

Frank A. Krueger edited this page Mar 14, 2018 · 21 revisions

This guide will show you how to use Ooui.Wasm to build a web assembly version of your app.

First we will build the default template project that prints "Hello World!" to the console.

Once that's working, we will build a UI using the HTML DOM.

All of these steps are written using the command line on Mac, but you can instead use Visual Studio and Windows to accomplish the same thing!

1. Create a new app

mkdir MyApp
cd MyApp
dotnet new console

2. Reference Ooui.Wasm

Ooui.Wasm is a package that references the Ooui package and contains a build target to generate the web assembly build.

dotnet add package Ooui.Wasm

3. Print hello world

Make sure Program.cs looks something like:

using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

4. Build the app

dotnet build

(The first time you build with Ooui.Wasm will be slow. That's because it's downloading the mono wasm SDK.)

In addition to building your app, this will also generate all the files you need to run your app in a web assembly. Those files are put in the dist directory. Let's take a look:

ls -al bin/Debug/netcoreapp2.0/dist/

-rw-r--r--  1 fak  staff      960 Mar 14 11:44 index.html
drwxr-xr-x  4 fak  staff      128 Mar 14 11:44 managed
-rw-r--r--  1 fak  staff   167240 Feb 28 20:39 mono.js
-rw-r--r--  1 fak  staff  1769591 Feb 28 20:39 mono.wasm
-rw-r--r--  1 fak  staff    14304 Mar 14 11:44 ooui.js
-rw-r--r--  1 fak  staff      284 Feb 28 20:39 server.py
  • index.html is a static web page that is custom generated for your projects and lists all of its dependencies and its entry point.
  • mono.js is a bridge between the browser's javascript world and mono running in the web assembly. You can blissfully ignore its banality.
  • mono.wasm this is it - the big enchilada - mono running in a web assembly.
  • ooui.js is the standard Ooui JS library that makes working with the DOM easy.
  • server.py is a terrible hack. Sorry. So you would think you can just load index.html and see your app run. That would make sense. But that won't work. :-( Problem is, wasm is new and browsers refuse to load it from your local disk. To work around this, we need a dumb static content web server. This is it. Sorry it's in Python, let's fix that...
  • managed is a directory that contains your app's assemblies. Let's look:
ls -al bin/Debug/netcoreapp2.0/dist/managed/

-rw-r--r--  1 fak  staff     4096 Mar 14 11:44 MyApp.dll
-rw-r--r--  1 fak  staff  3675136 Feb 28 20:39 mscorlib.dll

We can see that our app is only 4k, but it depends on mscorlib (as all apps do). The total app size is less than 4 MB and caches nicely. (Yes, yes, we can do better!)

5. Run the web assembly app

cd bin/Debug/netcoreapp2.0/dist
python server.py

Your app is now running on http://localhost:8000

If you open that page you will briefly see "Loading..." and then a blank screen. That's because our app doesn't have a UI and just prints to the console.

If you open the browser's console and refresh the page, then you should see Hello World!

Hit Ctrl+C to kill the web server.

6. Build a UI

Edit Program.cs to be:

using System;
using Ooui;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            UI.Publish("", CreateCounter());
        }

        static Element CreateCounter()
        {
            var count = 0;
            var countLabel = new Span(count.ToString());
            var upButton = new Button("Increase");
            var downButton = new Button("Decrease");

            var counter =
                new Div(new Div(upButton),
                        new Div(countLabel),
                        new Div(downButton));

            void ChangeCount(int amount) {
                count += amount;
                countLabel.Text = count.ToString();
            }
            upButton.Click += (s, e) => ChangeCount(1);
            downButton.Click += (s, e) => ChangeCount(-1);

            return counter;
        }
    }
}

This is a little app with a counter that can be incremented and decremented - written using the DOM (note the use of Div and Button).

All wasm apps must Publish a root element to be displayed.

7. Build and run the UI

dotnet build

cd bin/Debug/netcoreapp2.0/dist
python server.py

Now when you go to http://localhost:8000 you will see the counter UI!

8. Deploying your Web App

Since web assembly apps run locally in the browser, serving them is a breeze.

Copy the dist directory to your favorite static web server. That server can be anything from Azure, to Amazon S3, to some Apache Thing running Linux Something.

Clone this wiki locally