WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++, C# and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together.
Who Are Using WebAssembly?
Google: Using WebAssembly technology to make Gmail faster, and Squoosh, an image compression tool produced by their ChromeLab team, also compiles several common image codecs into WebAssembly for efficient image compression;
Mozilla: Developing WebAssembly as a new generation of Web technology;
Unity: Use WebAssembly to build a high-performance game engine;
AutoCAD: Using WebAssembly to implement CAD applications that run on the Web;
SketchUp: Using WebAssembly to implement a 3D modeling application that runs on the Web;
Figma: A collaborative design tool that runs on the Web using WebAssembly;
Dropbox: Building a client-side accelerator with WebAssembly;
Microsoft: Using WebAssembly to accelerate JavaScript in the Edge browser;
TensorFlow.js: Use WebAssembly to run TensorFlow models in the browser;
HandBrake: Build a video converter using WebAssembly to improve performance;
WordPress In Browser: Through WebAssembly, you can run this classic PHP CMS application on the browser without any server;
Computer Museum in the Web Page The webmaster built a WebAssembly application that allows us to load some ancient operating systems on the page, which is very interesting.
How Do I Use It?
Through the introduction of WebAssembly - WebAssembly | MDN document, we can see that it has 4 loading methods. Among them, 1 and 2 will directly return a Promise that generates a WebAssembly instance, and 3 and 4 will return a WebAssembly.Module, which Returns a WebAssembly instance after being executed. It can also be seen from their names: 1 and 2 are instantiated, and 3 and 4 are only compiled (not instantiated).
WebAssembly.instantiate() The main API for compiling and instantiating WebAssembly code, returning a Module and its first Instance instance.
WebAssembly.instantiateStreaming() Compile and instantiate a WebAssembly module directly from the streaming underlying source, returning both the Module and its first Instance instance.
WebAssembly.compile() Compiles the WebAssembly binary into a WebAssembly.Module without instantiation.
WebAssembly.compileStreaming() Compiles WebAssembly.Module directly from streaming underlying source code, instantiating it as a separate step.
Whether it is to initialize the Web Assembly module from Streaming or bufferSource, it is just a process of loading .wasm file, and we can choose proper loading method depends on our actual needs. After loading through the above method, we will get a WebAssembly.Instance object. Through this object we can access its internal variables and functions.
One Simple Example
Instantiating A WebAssembly Module Via WebAssembly.instantiateStreaming
WebAssembly has a binary format and a text format. The binary format (.wasm) is a compact binary instruction format for a stack-based virtual machine and is designed to be a portable compilation target for other higher-level languages such as C, C++, Rust, C#, Go, Python and many more. The text format (.wat) is a human readable format designed to help developers view the source of an WebAssembly module. The text format can also be used for writing codes that can be compiled to the binary format.
WebAssembly binaries can be compiled from multiple languages (C/C++, Rust, Assembly Script, C#…), see I want to… - WebAssembly. Here I use C code to compile .wasm as an example.
We can use emcc in our shell to compile .c file to .wasm file.
Writing C Code For Compilation
Still I use a+b as an example. This C file module contains only one add function, which takes two numbers as input and returns the sum of their addition.
There is a strange #include <emscripten/emscripten.h>, what is it? emscripten.h provides some public C++ APIs, see emscripten.h for details.
You can see that I added the EMSCRIPTEN_KEEPALIVE macro to the add function, which tells the compiler to keep it and export it, which allows us to access it when we access the WebAssembly instance with JavaScript.
Compile the .wasm file
Excute the following command in our shell
bash
1
emcc add.c -s WASM=1 -o add.html
The above command arguments is explained as follows:
emcc is the command line command for Emscripten
-s WASM=1 tells Emscripten to output wasm files, if this parameter is not specified, asm.js will be output by default
-o add.html tells the compiler to generate an HTML document named add.html to run the code, as well as the wasm module and the corresponding JavaScript glue code used to compile and instantiate wasm, so that wasm can be used in the web environment used in
After running the above command, there should be three more files in your WebAssembly directory:
add.wasm Binary wasm module code
add.js A JavaScript file containing the glue code, through which native C functions are translated into JavaScript/wasm code
add.html An HTML file used to load, compile and instantiate wasm code, and display the output of wasm code on the browser
Run It With JavaScript
Open the add.html file generated above with an http server. After opening the page and using devtools, we can find that the .wasm file we compiled has been automatically loaded. This is because the add.js we compiled has already generated the relevant code needed to instantiate WebAssembly for us.
We can find the instantiateAsync function which is the key to load our WebAssembly Module.
In this example, add.js initializes the WebAssembly instance and puts it in a global module Module, so we can access the add function in the C module through Module.asm.add.
Implement WebAssembly In Other Applications
Through the demo above, we know that we can use JavaScript to initialize WebAssembly and use it, but there is a problem that the js glue code generated by emcc creates a global variable named Module. But what if I:
Don’t want to use Module as a variable name, because I may already have this name
Don’t want to load WebAssembly modules in the first place
No need to use WebAssembly modules in Node.js environment
Want to simplify the js glue code to achieve faster loading speed
Here are my answers:
Customize our WebAssembly module name When compiling with emcc, add the -s EXPORT_NAME="CustomModuleName" parameter to customize the module name
Loading WebAssembly modules asynchronously When compiling with emcc, export an ES6 JavaScript module with -o target.mjs, or modularize it with -s MODULARIZE. -s MODULARIZE can be used with -s EXPORT_NAME="CustomModuleName". After loading the js glue code, you can use CustomModuleName() to instantiate WebAssembly. Among them, CustomModuleName function returns a Promise.
When I don’t need Node.js related code When compiling with emcc, add -s ENVIRONMENT=web, the compiled glue js code will not contain Node.js related logic.
Simplify the glue js code When compiling with emcc, add the -O3 parameter to minify. The effect of add.c in this example is: add.js(10KB/53KB), add.wasm(72B/916B).
When we use WebAssembly for more complex calculations, in order to avoid affecting the browser rendering process, we can put it into Web Worker to run. You can refer to Using WebAssembly with Web Workers - SitePen.