We’ve been doing web development for 30+ years and in all that time have you ever stopped to think, “This SPA needs more C++”? Well thanks to the power of WebAssembly you can finally bring C, C++, Rust, Go and other high level languages to the browser.
For this talk, we’ll look at some of the fundamentals of WebAssembly, how to incorporate it into our development process and ultimately what it looks like to build an application that uses a mixed development stack.
— Asim Hussain (@jawache) June 20, 2019
Kicking off with a WAT hello world example that was far too long to write down 😉 You can see the general vibe by looking at other hello world examples for WASM. The take away is that you have to do a lot of really low level stuff you’re probably not used to.
WASM is not the most readable language! Assembly languages are pretty complicated in general and not so accessible to most people. There is a reason compiled languages are popular.
But let’s step back and really start with What Is WebAssembly? It’s the evolution of asm.js, which was created to enable high-performance applications to run in the browser. asm.js was designed as a compilation target rather than a language you write by hand.
WASM is also designed as a target and not a language most people will write by hand. With WASM you end up with a compiled WASM binary written in some other higher order language.
— Simeon Johnson (@lostumbrellas) June 20, 2019
The browser needs more C++ in it. – No one, probably ever
So what does WASM mean for JS devs?
It’s not a JS replacement. It’s possible to effectively replace JS, but it’s probably not the right way to go. Another platform tried to do that… it was called Flash. Browsers are really good at executing JS; and JS is great for things like DOM manipulation. WASM is good at other things. They complement each other.
- Module – WASM binary
- Instance – a running WASM module running in a VM in the browser
- Memory – an ArrayBuffer shared between JS and the VM. It only stores values. This does allow values to be passed between modules.
- Table – like memory, but for function references
But why? Why would we use it?
- Sandboxing – the more we build in the browser, the more risks there are (security, stability, memory leaks). Running in a dedicated memory space helps address that.
- Shared client & server – not every server app is going to be written in JS, because it’s not the best language for all problems.
- Image manipulation – eg. when we want to edit a photo. There are great libraries in C++ which we can compile to WASM and use in the client and server without differences.
- Complex maths – WASM is better suited to heavy mathematics than JS
So what is it like to developer with WASM?
- First, pick your language… something like C, C++, Rust, C#, F#, Go. Aaron picked Go as he wanted to learn it and it was a good opportunity.
- Convert to a web application… Webpack is well suited to transpilation tasks, so Aaron used that
- Create a UI over the top… React works well, although you can use anything including gasp raw HTML
This was a super quick look at WASM. It’s here, it’s real, it’s in browsers. Be aware the binaries can be pretty big so think about appropriate cases to use it.
Use WASM to extend your app. Sandbox parts of the app that could benefit from being sandboxed; or push something to the client that could previously only be done on the server. Look at places it would be useful to reuse code.
While JS is great it’s not the best language for all cases – each language has its strengths and weaknesses.
(mellow music) (audience applauds) – Thanks, John, and thanks, everyone, for having me here. The article I think John was referring to is where I said that Microsoft needed to kill Internet Explorer, and this was several years before they actually announced Edge, and I was actually a Microsoft MVP at that point in time for, ironically, Internet Explorer. So I wrote this article about why they should’ve killed the product that I was supposed to be supporting in the community.
But I’m not here to talk about Internet Explorer because it doesn’t support WebAssembly.
I’m here to talk about WebAssembly in the browsers. So who’s writing WebAssembly code like this today? No one? Good, ’cause if you were writing the WebAssembly Text Language, which is what I’ve got up on screen, I’d like to speak to you afterwards and work out why. But we’re gonna be talking about WebAssembly today, and I’ve been talked about by pretty much every speaker so far, so there’s no pressure on me.
So now it’s time to learn WebAssembly.
So what we’re doing here is we’re starting off by bringing in a function from our host of our WebAssembly application called log from an object called console.
It takes two arguments.
They are of int 32 types that are being passed into it, and we’ll get that sent to our WebAssembly machine. I’m then going to be requesting one page file of memory in my WebAssembly application, and then I’m going to be putting some data into that. So I’m gonna be popping this onto the stack at position zero and I’m gonna put the value of Hi, H-I, in there, and that’s what will be in our memory table. Finally, I’m gonna be exporting a function from WebAssembly called writeHi.
That function will push two values onto the stack. The first one is gonna push a 32-bit integer constant of zero, and then it’s gonna push the second one, which is a 32-bit integer constant of two.
Both those will pop onto the stack.
We’re then gonna call that log function, which will then pop those both off the stack, and hopefully we will write out a message, or we’ll send some values at least correctly through to our log function.
Defining our memory table at the top there, and it’s gonna have an initial size of one. We’re not gonna grow this memory table, but it’s gonna look like that.
We then have a log function to find.
It has two arguments passed into it, an offset and a length.
We’re going to be converting that memory buffer into a Uint8Array.
We’re gonna be then taking a subsection of that memory buffer based off of the two arguments we’ve been provided.
That’s gonna be decoded as a utf8 string into a value that I can console.log to the browser. I’m then going to create an object that’ll pass through to my WebAssembly application when it starts. I will then fetch my WebAssembly binary.
I will then instantiate our application, and hopefully with all of that, I will write out the message to the console of Hi. Thank you for coming to my WebAssembly talk. (audience applauds) So that’s a little bit confusing, if I’m to be honest. It’s probably not the most readable language. I did do Assembly programming back in university. I learned how to convert Assembly to binary and back from that to Assembly, and it’s not something that I wanna spent a lot of time doing.
But I kind of just jumped this talk straight into looking at raw WebAssembly, and that’s probably not going to be the most accessible thing to most people.
So let’s take a step back and think about, well, what is this thing that I’m talking about and why is it of interest to us? So what is WebAssembly? That’s probably where I should’ve started, not just started with code.
WebAssembly is essentially the evolution of the asm.js specification, or at least loose specification.
So they could then target those optimizations and skip things like the jit step so that you didn’t have to do that and hopefully run your application a lot faster. One of the earliest examples that they did with this was run the Unreal engine in the browser, in one of the earlier versions of Firefox.
I’m gonna obviously focus on the browser today, but you can use this with node.js.
Come see me afterwards if you’d like to know more about that end.
So what we get is a compiled binary.
This is still designed as something that we would compile from another higher language like C, C++, Rust, Go, et cetera, and not actually write ourselves.
Like, you don’t wanna be writing that stuff that I showed on the first slide.
That’s a little bit undesirable.
We no longer have to worry about, well, how much is, memory’s available on this machine? I’m giving that directly to it.
Or what is the hardware that is available to this runtime? Well, that’s been denormalized by the fact that this is running in a virtual machine. It only supports a small set of data types. It supports 32-bit and 64-bit integers and 32-bit and 64-bit floating point values, which means that that’s gonna be kinda difficult to build complex applications if you’re just running it directly.
That’s why it is still seen as a compilation target of higher level languages. C and C++ were what it was originally designed around, but many other languages have started targeting this. Go, Rust, .NET, and a whole bunch of other things. Now, I admit that I didn’t actually get to spend a lot of time building cgi.bin applications back in the day, but I don’t think I’ve ever sat there and gone, you know what I need for my web application? It’s more C++.
Particularly running in my browser.
I remember another platform that did that.
It’s called Flash.
A lot of stuff when we’re working with the DOM is working with strings, and as I mentioned before, WebAssembly doesn’t have strings as a data type. It just doesn’t exist.
We’ve only got numbers.
It’s very difficult to represent a full DOM as int 32. It’s gonna be not highly accessible.
But there’s certain things that WebAssembly will be very good for.
Just some terminology so that we’re all on the same page as we talk about WebAssembly. We have our WebAssembly module.
This is the binary that we get from our compilation step, whether it’s output of a C compiler or a Rust compiler or whatever it might be. This is the thing that you’re gonna fetch in the browser or load in a node.js runtime that will be executing our WebAssembly application. We then create an instance of the WebAssembly virtual machine using that provided binary. We can create multiple VMs inside of a single application, so the browser can spawn as many Assembly VMs as you want. Just you’ve got to make sure that you think about the performance overheads of spinning up a whole lot of little VMs inside of your browser. But you can definitely do that.
We can, we then have memory.
But we can also share memory across VM instances. So if we have, say, three different little WebAssembly VMs that are running, they can actually share that memory, and we can then pass values between them quite easily. Because memory is used to pass more complex data types back and forth, so if we didn’t wanna expose a string, if we can’t actually directly work with the string, we have to return that through memory or we have to put that into memory and read the memory buffer.
A table is kind of like memory, as well, except the table is used to pass function references, not value references.
We can also expose functions from one virtual machine to another virtual machine using tables, assuming that they’re using a shared memory, or shared table inside of our VMs.
Okay, but why? Why are we wanting to use WebAssembly, or why is it something that could be of interest to us building applications? I think the idea of sandboxing is probably the most compelling reason to use it.
We’re building stuff in the browser and it’s getting more and more complex, and if it’s all running in a shared user space, we have the risk of things like cross-site scripts being able to access values or information inside of our applications that we might not want exposed. Maybe we’re building an application that has some level of cryptography that it does in the client.
Well, do we want that running in the same memory space of potentially untrusted code? So we can use this to sandbox things withinside of our browser runtime.
And complex mathematics.
That’s its only data type.
So if we wanna do something that’s got complex mathematics. Maybe we’re building some ML models.
A lot of the really early demos of WebAssembly and its predecessor asm.js was around bringing game engines to run in the browser. So that’s where I kinda see WebAssembly playing out. It’s not the next version of a React is getting written in WebAssembly, but it can be used to supplement our applications. So what’s it like to build a WebAssembly application? Well, the first thing we’re gonna need to do is pick a language that we wanna compile our WebAssembly programme from, and we could do something like C or C++.
Those were a lot of it was designed around. We could use Rust if we wanna be a little bit more hipster than just using C, ’cause that’s what cool kids are using, apparently, for high-performance computing these days.
We could do something with .NET, C# or F#.
Both have compilation targets for WebAssembly. We could write the WebAssembly Text Language from that first set of slides, but that would be a little bit difficult.
But when I started exploring this and working out where I could use it, I decided to go with Go, because I wanted to learn Go and this seemed like a great way to do it.
So I built a little Go application that is designed for bringing a list of conferences from a markdown file that exists online.
I’ll just show you how this works.
So this is just a console application that I’ve got running here.
It dumps, it parses a markdown file.
It then exports that as, it reads the syntax tree of the markdown file, does some manipulations to that, and then just dumps that out to my terminal, and I can see a whole bunch of events that are happening around Australia.
Here it is.
This is all on GitHub and the links will be available afterwards. And also, I’m not trying to convince you to write Go lang or anything like that.
I’m just using this as an illustration of building a WebAssembly application.
But this is my application.
It’s doing a, runs a HTTP get to download the file. It then uses a little library that I wrote that walks the syntax tree using a parse markdown function. It will then walk the syntax tree, build up a new object type, and that will be then sent down to, or return from this function, and then I’m just serialising that as JSON to dump to the console, because that was the easiest way for me to represent it. So this is all quite useful ’cause I’ve got this application that now works, but I wanna convert this into a web application, or I wanna use it in a web application.
So I think about the kinds of tools that we build web applications with, one of those being Webpack.
I then need some kind of UI that I wanna build this on top of, because I wanted to treat this as a web developer. I’m not trying to be a Go lang developer here. I’m trying to extend a web application with some Go lang functionality.
So I use React.
It’s just my library of choice.
But that could be, you know, it could be View, Angular, or raw HTML.
Yeah, but again, I was looking at the kinds of tools that I use as a web developer.
So what’s, so let’s bring this all together and have a look at how that works.
Jump over to my other one here.
I have a React application.
It just is a fairly basic React application that does some mounting of components which then goes out and then wants to download a bunch of markdown files.
So we go down to this downloadYear function. It uses fetch in the browser, because the browsers are very efficient at downloading files, so I thought I’d use fetch rather than, like, putting that, there’s no point putting that inside of my Go lang application.
You know, the browser knows how to fetch a file pretty well. So I can do that, and then I have to get to this Go lang application. So I start with import something from a .go file. Interesting.
And then have a Go lang file here that calls to that markdown tools, which does the syntax tree walking and then generating the object model.
The only difference here, instead of just returning the objects, it serialises it as JSON so I can then consume that in the browser, and I registered that for use withinside of my web application.
And it’s exposed asynchronously, so I can use promises against it.
Just treats it like normal working against a web application.
And then I define a loader inside of my Webpack config as a loader that I’ve written to do that, and it all works nice and seamlessly together. And then I end up with a web application that looks kind of like this.
My design skills are top-notch, as you can see here.
But what I’ve got is, if we see here, is a whole bunch of events that are happening around, in 2019 around Australia.
I can then filter them by state.
But then this is just a single-page React application. So just to wrap up, that was a very quick look at WebAssembly, I’m aware. But WebAssembly, it’s real, it’s here.
It’s in all of the browsers.
It’s been in Chrome for a while now, which means that it’s in the Edge version of Chrome. There’s some rudimentary support for it in Edge, not Edge Chrome.
I’ve found some issues particularly with the way that you have to instantiate larger binaries, which, something like Go lang, CPython, and .NET, they produce much larger binaries.
I think that application that is running just to parse the markdown is around about four meg. So this is not for your, like, really super small applications.
You will often end up with quite large WebAssembly binaries. So all the evergreens on the desktop work fine. It’s kind of hit and miss with mobile browsers. Chrome on Android is kind of the most up-to-date one because it’s so close to Chrome on desktop. I haven’t had a lot of chance to test with iOS ’cause I just actually don’t have an Apple device that I can test with, but I would expect that that’s not too far behind ’cause it has reasonable support with Safari, as well. Use WebAssembly not to replace what you’re building at the moment, but to extend it.
Sandbox parts of your application that might need to be sandboxed or could benefit from being sandboxed.
So consider putting those workloads in a language that can be compiled to WebAssembly and then just call those binaries as a WebAssembly application to extend the application that you already have running inside of the browser. Just wanted to finish with a couple links that might be of relevance.
So the journey that I went on from someone that had no idea about WebAssembly to building that application that I just had there, you’ll find that at the top link, aka.ms/learn-wasm, and there’s a heap of great resources on webassembly.org that’s behind the specification.
I’ll also tweet out these links, as well, with the code hashtag, so don’t feel like you actually have to write them down frantically before I click to the next slide or blank it so that you just go, oh, I was, what was that last letter? M.
But WebAssembly is here.
It’s a really interesting bit of technology. I would highly encourage people to experiment with it, see where it could fit into the kinds of applications that you’re building, and think about what it can be used for for the next phase of our web applications. Thank you for listening.
(audience applauds) (mellow music)