Getting started with Rust WebAssembly apps for the SAFE Browser

WebAssembly is a recent addition to browsers that enable the use of other languages than JavaScript for writing web apps. Here is a short guide to writing a Hello World application in Rust and getting it running as a SAFE web application.

There is a working demo at safe://hello.webassembly. It only prints “Hello World” in the developer console, so you need to open that to see the message.

First you need to install the Rust language and Emscripten to be able compile your Rust code to WebAssembly.

You can use the following guide for that if you don’t have this installed already.

Once you have installed it, create a directory for the project and place the following in the file hello.rs

fn main() {
println!(“Hello World!”);
}

Then you need to create an index.html file in the same directory with the following content. Replace the url variable that’s set to safe://hello.webassembly with your own url.

<html>
<script>
var Module = {};

function runWebAssembly(appToken, url)
{
  return window.safeApp.webFetch(appToken, url + 'hello.wasm')
  .then(buffer => {
    Module.wasmBinary = buffer;
    var script = document.createElement('script');
    script.src = url + 'hello.js';
    script.onload = function() {
      console.log("Emscripten boilerplate loaded.")
    }
    document.body.appendChild(script);
  });
}

let app = {
  name: 'Hello Webassembly',
  id: 'net.webassembly.tutorial.webapp.example1',
  version: '0.1.0',
  vendor: 'webassembly'
}

function connectAndRun(appToken, funct)
{
  return window.safeApp.connect(appToken)
      .then(_ => funct().then(_ => window.safeApp.free(appToken)));
}

var url = 'safe://hello.webassembly/';

window.safeApp.initialise(app)
  .then((appToken) => connectAndRun(appToken, function(){ return runWebAssembly(appToken, url); }))
  .catch((err) => { console.error("Error from webapp: ", err); })

</script>
</html>

Next you need to compile the Rust code to WebAssembly with the following command

rustc --target=wasm32-unknown-emscripten hello.rs

The files hello.js and hello.wasm was now created by the compiler. hello.wasm is the actual compiled rust code while hello.js is boilerplate javascript code needed to load and run the WebAssembly file.

The last step is to upload index.html , hello.js and hello.wasm to your site, then you should be able to go to your site and see “Hello World” printed in the dev console.

Next I’ll be looking into how to call JavaScript functions from Rust to be able to call the SAFE JavaScript API from the Rust web application and store some data on the SAFE Network.

18 Likes

Just to say, delighted to see this. I keep going to wasm as I am no JS developer and like the idea of missing out my hated FFI layer is possible. I have great hope for this one and will watch with much interest to see how you get on.

Nice one :+1: :+1: :+1:

5 Likes

Wow, this is an eye opener.
Totally uncharted land for me (more or less goes for rust too).
Found this blog post: http://asquera.de/blog/2017-04-10/the-path-to-rust-on-the-web/ which goes into some additional details about it.

I’m wondering, what capabilities does this code have when running in the js VM? It is still shielded off from the host machine, right?

From an outside perspective I get curious also about what the advantages here are, except that rust coders (among others) can use their preferred language for coding web apps (I guess?).

2 Likes

Wow from me too. Very interested to learn this is what web assembly is about - I probably read it already but this rams the point home and hopefully makes it stick! :slight_smile:

Just to add, ‘preferred’ bringing the advantages of Rust as in much less error prone coding and catching errors earlier (at compile time), which will be particularly useful for certain areas of programming.

Not sure of the disadvantages - because possibly you can mix languages, I guess you could still use the many useful libraries and frameworks available in JS? - except perhaps added complexity and maybe small additional load time for simple apps.

2 Likes

It’s no different than js in this regard.

There’s two reasons for web assembly really. One is to enable the use of many different languages and reuse existing code on the web, the other is performance, web assembly can get closer to native performance than javascript.

3 Likes

The main disadvantage is really the same as that of having many different programming languages for desktop/server apps. If everyone just used one single programming languages, certain things would be simpler, everyone just has that one language they need to learn and think about, but the advantages of having many programming languages, rather than just a single one, vastly outweigh this disadvantage.

You can call js code from webassembly and vice versa.

3 Likes

So cool! Thank you for posting.

I tweeted Beaker browser to confirm that web assembly is available for use.

Here I see a WebAssembly object in the Beaker console

Can’t wait to make time to play with this.

7 Likes

Any Windows users whom also want to play, it’s not quite a smooth process to install and utilise Emscripten.
Here’s a guide: https://github.com/hunterlester/rusty_safe_web#emscripten-setup

4 Likes

Take a look at the source code of stdweb.

Also there is this thing called cargo-web which will install emscripten (linux only right now) for you and make rust webdev easier, but there is one downside it only supports asm.js (the predecessor of wasm).

edit: just saw this on “this week in rust”: lord_io/blog/2017/wargo/ (“Sorry, new users can only put 2 links in a post.”)

3 Likes

I tested wargo on a simple bin app in rust, it worked, kinda. You do need to tell llvm to not go through main and complete. In any case it works a bit, but if you then have libs that are not no_std only then there are issues AFAIK. Anyhow wargo is a great try, I see the rust team looking at wasm and agreeing the compiler targets right now are not tier 1 ready at all. So a bit of work to do, but that team will get it, if anyone can.

Interesting to see the c++ emscripten projects have not yet got to create exciting stuff yet, I wish there were movement here, but its for sure very interesting.

4 Likes

native wasm support for rust(work in progress): https://github.com/rust-lang/rust/pull/45905

3 Likes
  1. wasm support got enable: https://github.com/rust-lang/rust/pull/46115
  2. there is a chance for stdweb to support the wasm target without emscripten: https://github.com/koute/stdweb/issues/36
4 Likes

Over the weekend I started playing with wasm-bindgen which,

allows JS/wasm to communicate with strings, JS objects, classes, etc, as opposed to purely integers and floats.

Notable features of this project includes:

Exposing Rust structs to JS as classes
Exposing Rust functions to JS
Managing arguments between JS/Rust (strings, numbers, classes, objects, etc)
Importing JS functions with richer types (strings, objects)
Importing JS classes and calling methods
Receiving arbitrary JS objects in Rust, passing them through to JS
Catching JS exceptions in imports

I began building a simple safe_app_wasm library but ran into compilation issues having to do with dependency crates that only support Windows or Linux target families, when my target is wasm32-unknown-unknown, summarised in this issue.

You’ll see that these two crates memmap and fs2 that we rely on need either a Windows or Linux target.

Even when rust-wasm decides how to treat wasm32-unknown-unknown target, it looks like 3rd party crates will still need to implement wasm support.

wasm-bindgen is much cleaner than my experiments using Neon and I think it would be worthwhile to spend time either opening issues in crates that we want supported or to open PR’s on those crates to implement wasm.

5 Likes
1 Like

An IDE that can be run in the browser for WebAssembly: https://hacks.mozilla.org/2018/04/sneak-peek-at-webassembly-studio/

5 Likes

For a higher-level library to complie wasm from Rust, might be relevant to consider yew: https://github.com/DenisKolodin/yew

2 Likes

Have you guys checked this book out?

2 Likes

What is the current state of using Rust, and a Rust-based web framework such as Dominator or Yew as @jonas mentioned, for SAFE apps via WebAssembly vis-a-vis SAFE Browser?

Safe Browser is chromium based, so whatevers working in the appropriate version should be working for the Safe Browser. I personally haven’t attempted anything beyond a couple basic wasm tutorials in my time (and not in SB). But there’s no reason it shouldn’t work AFAIK

2 Likes

What is the most recent example demonstrating loading an SPA as a wasm file with minimal JS bootstrapping it?

Also, would the JS and wasm files be first stored to SAFE and then referenced in the fetch with their xor-url?