Blog post cover
Arek Nawo
08 Sep 2020
7 min read

WebAssembly for web developers

When WebAssembly was first announced, it caused excitement, but also some fear in the web development community and beyond. Programmers coming from languages like C++, or Rust surely appreciated the fact that they now could target the broader demographic of Web users, while putting in much less effort than was previously required. Web developers, on the other hand, especially those experienced mainly with JavaScript and related ecosystem, could sometimes experience fear about the future of their language-of-choice.

Now, the excitement has settled a bit, but it doesn’t mean that WebAssembly has too. No, in fact, it’s continuously being developed, new, very important features are being added, and more and more applications using it pop up every day. But its impact right now is much smaller than some might previously speculate. Its primary use-case is still limited to computation-heavy numeric applications, which don’t get me wrong is quite important, but not as wide-spread in the Web. Perhaps it’ll change in the future, or maybe even WASM shift its focus and become more popular in environments other than the Web - we’ll see.

However, in this article, I don’t want to speculate on the future of WASM. Instead, I’d like to share something with you that - if you’re a web developer like I am - might spark your interest in WASM, or at least make you stop worrying about your job for the time being. ;)

Meet AssemblyScript

So, today I’d like to introduce you to AssemblyScript - a weird, but certainly appreciated mixture of TypeScript and WASM, where one serves as the source language and syntactic basis, while the other as the compilation target.

TypeScript recap

You’ve heard of TypeScript, right? Undoubtedly the most popular typed superset of JavaScript. But why use it as the source language instead of the basic JS?

Well, the answer is obvious and it has to do with types. In JS with its dynamic type system, although we might be able to detect the data types for different values, it’d be rather inaccurate and almost surely inefficient.

TS with its types is an ideal candidate for this kind of use-case. Statically-typed and very popular - great JS-like source for WASM target.

Under-the-hood

So, with familiar TypeScript syntax from the outside, how does AssemblyScript work on the inside? From the most upper-level of abstraction, it uses Binaryen (WASM toolchain and compiler infrastructure) to (indirectly) compile TypeScript (or rather a very strict variant of it) to WASM.

Concept of mixed levels

In general, I think the concept is pretty great. The convenience of a very high-level language, with the speed of a relatively low-level target. That’s especially true for web-developers who’d prefer to learn somewhat-familiar TypeScript syntax, without bothering with languages like Rust or C++.

So, yeah - great idea! Now, how about its execution?

Example

Let’s take a look at an example snippet of AssemblyScript code. By the way - the best place to play with AssemblyScript is WebAssembly Studio.

export function fib(n: i32): i32 {
  var a = 0,
    b = 1;
  if (n > 0) {
    while (--n) {
      let t = a + b;
      a = b;
      b = t;
    }
    return b;
  }
  return a;
}

Now, I hope you know TypeScript, because if you don’t, then stop right here and go read my 3 part introductory series and all the other content on it. You’re back or you already know TS? Good.

What you see above is pretty much nothing but some TypeScript code. The example is taken from the official docs and calculates the value of the Fibonacci sequence for the specified index - basic stuff.

The only differences from the usual TS code are in the types. Notice how at the beginning of the function, we use i32s, instead of TS’s usual numbers. This is part of AssemblyScript’s “additional features” meant to make TypeScript syntax better suited for WASM compilation.

On top of TypeScript

Taking “pure TypeScript” and using it for WASM compilation would be quite hard (not JS-to-WASM hard, but still). That’s why AssemblyScript, in addition to the basic JS/TS functionalities, provides types, globals, and generally a whole standard library to make the WASM compatibility easier.

Familiar feeling

The nice thing about all these additions is the fact that they feel just like normal TypeScript. The int32 feels just as you’d do type int32 = number yourself - and the same goes for all the other types. Other than that, all the functions, methods, objects, classes, etc. included in the standard library can be used just like any other TS code you’ve seen before.

Change of mindset required

The downside of this, however, is that you have to rely on this standard library to create any more advanced code. Because AssemblyScript has a different target than a usual TypeScript code (WASM vs JavaScript engine), it can’t just use all the goodness available in such an environment. That’s the reason AssemblyScript comes with its own standard library that replicates as much of usual JavaScript APIs as possible - Arrays, Maps, Sets, Math methods, and all that included. It also comes with an optional runtime for handling the memory management - basically a simplified WASM-compilable equivalent of JS engine’s garbage collector.

All this might not be surprising to you if you look at AssemblyScript from a perspective of a separate language. But because it’s heavily based on TypeScript, which usually has access to all the goodness the Web offers, it might be a bit mind-boggling when you first use it. Slightly limited standard library, heavy focus on numeric computation, and no access to any Web APIs might require a slight change of mindset if you’re a web developer.

Some warnings

Now, you have to understand that I’m not trying to keep you away from AssemblyScript. I’m simply pointing out some of its natural ups and downs which you might experience when working with it. None of this indicates AssemblyScript is bad or anything like that - just that it’ll require you to change your mindset a bit.

Perfect balance

The primary audience of this article and even AssemblyScript itself are web developers. If you’re one of them and want to try out WASM without much learning overhead, AssemblyScript is your best choice. Sure, you can learn Rust, C++, or another compile-to-WASM language just to use WASM, but at this point in time, I personally think that the results of this investment would be disappointing. Unless you plan to use the newly-learned language in some other way, AssemblyScript provides the perfect balance between familiarity of JS/TS and performance of outputted WASM.

Real-world projects

Going a bit further, if you’d like to use AssemblyScript in a real-world project, which is totally possible (even though the language is at version 0.x), then there are some things you need to keep in mind.

Primary use-case

First and foremost, don’t overuse it. While not really a limitation of AssemblyScript itself, WASM is mostly suited for heavy numeric computational tasks. Applications like mathematical visualizations, games (especially logic and graphics calculation), simulators, etc. can benefit from WASM. But when used improperly for cases where e.g. complex string-based operation or UI are involved, you might even see performance loss!

Apart from WASM not being designed to do this, the part where it integrates with JavaScript in the browser, also carries some performance hits. You need to know when and how your app can benefit from WASM, and not push it to places where it should be.

Project structure

Secondly and lastly - you need to organize your project correctly. Because AssemblyScript feels a lot like traditional JS/TS code you write day-to-day, it might be tempting to integrate it just like any other JS/TS code you did before. Sadly, it’s a false feeling, and I recommend you keep your AssemblyScript in a separate folder, away from your usual JS/TS code to avoid confusion.

Bottom line

I hope this article allowed you to learn about the existence of AssemblyScript, or maybe even sparked your interest in trying it out to integrate the power of WASM to your own project.

When used properly, WASM can make your app noticeably faster. and as time goes on, I hope we’ll see it only getting better. And with projects like TypeScript or AssemblyScript, I can assure you that you don’t need to worry about the state of the JavaScript and its usefulness for a long time.

For more content on WASM, TypeScript, and JavaScript in general, follow me on Twitter, Facebook, or through my newsletter. Thanks for reading and happy coding!

If you need

Custom Web App

I can help you get your next project, from idea to reality.

© 2024 Arek Nawo Ideas