This is a living document. Come back often to get updates.
The role of WebAssembly
Wasm in Composability
In case you have arrived here from the outer world and have not had the chance to read my short explanation about WebAssembly and why it may matter to you, you can find it here.
In this page, we will deep dive into the core concepts of this technology, and why it's important in the current composability landscape. Do we need Wasm to build more efficient micro-architectures? I believe, yes, we do. And I will try to explain here why.
The Origin of WebAssembly
I first heard about WebAssembly at the end of 2016, but I later learned it was born one year earlier. At the time, I was working as a Senior Frontend Software Egnineer and was very much into Web Performance. I was preparing a talk about http/2 to convince the people running systems and architecture in the company I worked at, to flip the switch for our servers, and while investigating about performance improvements, I came across WebAssembly.
What exactly is WebAssembly?
Where does WebAssembly code run?
I know you're itching to see some code, already. But I won't show you the binary, first, because the binary won't tell you much. Also the actuall binary output will depend on the compiler.
Let's see what the Web Assembly text instruction would look like, if we wanted to write a program that was called `hello_world` that would print to the screen: "I love to compose micro frontends in the cloud".
(module (import 'env' 'println'func $println (param i32))) (func $hello_world (export 'hello_world') (block $block (call $println (i32.const 0)) )) (memory 1) (data (i32.const 0)'I love to compose micro frontends in the cloud 0')))
Dissecting the textual instructions above.
In `.wat`, each instruction between a pair of a beginning
`(` and closing `)`, is an `s-expression`. We can use them to form a tree of nodes.
Let's explain the code above: the first node is a top-level construct or root node that defines the structure, in this case, the fundamental unit of code of WebAssembly: a module.
The second node, a child node, is declaring an imported function, in this case `println`, from an external module -and this is the beauty of it, the ability to interoperate-, `env`, taking a single param of type `i32` -yes, integer 32-bit in this case-. When we see a `$` means we are declaring a local entity, in this case, the local name of the imported function `$println``
`block` declares a new block of instructions that we locally call `$block` and then we are invoking our imported function `$println` inside of this block with `call`. Pay attention to how we are now pushing a constant value 0 to the stack, that we will use later `(i32.const 0)`.
The following child node, declares the memory with 1 page, equivalent to 65536 bytes.
Finally, we use the `data` node to stora a string constant in memory, starting at the address 0 that we previously declared, with the `\00` or null terminator that represents the end of a string in WebAssembly.
If you want to see different modules in action, you can go to wat2wasm and play with the demo tool. I loved it!
In sum: Do developers write binary WebAssembly binary code?
No. I don't think so. At least I wouldn't. What developers may write, is WebAssembly Text like the one we just dissected, which is a more human-readable format and is saved in files of extension ´.wat´, that can then be compiled to ´.wasm´.
However, to write WebAssembly text, you need to learn all WebAssembly concepts first. And it's definitely not trivial learning. You would need to learn about modules, memory -ergo a resizable ArrayBuffer that stores all the bytes in your module-, tables -another array but for references- and the concept of instance, which encompasses code and state.
I still don't recommend you write WebAssembly text or ´.wat´files, yourself.
image caption: Wasm in the browser
Wasm as a compilation target
But don't despair! We don't need to learn to write WebAssembly Text in order to create Wasm code. In fact, WebAssembly wasn't really designed to be created in this way. It was designed to be a portable compilation target for higher-level languages.
Languages that compile to .wasm
Having other programming languages compile to binary code that can be ran in the browser, and has access to Web Platform APIs, is the most appealing feature of this technology, and why it is so successful. It means that developers that were restricted to writing server-side only code, can now run their code in the client.
C# and .NET
There are other contexts where `.wasm` code is potentially executable, that I will describe further down.
I will try to keep this list up to date as much as possible, but you can also visit Fermyon's site where for sure they keep much better track.
What do you need to compile languages to Wasm?
What makes it possible for languages to compile to Wasm, is called the toolchain that supports conformance with the target language.
I am currently learning Rust, and the toolchain is described here.
It basically includes `cargo`, which is the default Rust CLI, `npm` for dependency management and `wasm-pack` to do the transformation to binary.
In the previous list, I made a reference to languages that support Wasm in the browser. But there are additional standarization efforts, to make it possible to run WebAssembly code not only in the client-side, but server-side and in IoT devices, for example.
WASI stands for WebAssembly System Interface and it's a modular API that provides the WebAssembly runtime sandbox, and the apps running on it, access to features of the operating system. You can read the introduction text here.
Rust and C/C++ have WASI-enabled toolchains and WASI programs can run on its specific runtime Wasmtime or in the browser, with the necessary browser shim.
So how can Wasm contribute to improve a composable architecture scenario?
But we also know that one of the characteristics of WebAssembly, is portability, and that we have shims that allow to run Wasm (WASI enabled) server-side or in devices. That multiplies opportunities to have super-performant execution contexts, literally anywhere where you may have the necessary infrastructure -a virtual or physical machine, or other forms of virtualization like containers- in the form of functions.
For example, as my code example above illustrates, you may have to import definitions that your specify in your code, like I do to use `pintln` from `env`, in the `.wat` file above. Even when Wasm code's format makes it lighter and faster, we still need to learn to optimize it, and that is specially true when Wasm is a compilation target for other languages, since they will inject dependencies necessaries via the toolchain. That may suppose a resource strain for the system running Wasm, when it's clientside, deteriorating the user experience by straining resources like memory.
However, when it comes to innovative forms of composition, a lot of the frameworks we discussed in the corresponding section of the site, are designed to build applications that may be either rendered or composed on this super fast and performant runtimes in the cloud, and use service workers and other mechanisms to improve client-side performance.
To wrap it, the demand for immediate feedback and transaction completion by the end-user, when that's possible in terms of connection, device capability, and protocol availability, may contribute to a more consolidated composite in terms of frontend distributed applications.
This website uses a technical cookie to save your cookie preferences in your browser. Additionally, it uses Google Analytics to analyze the traffic.