preface

WebAssembly is the future

efficient

While WebAssembly has a complete set of semantics, WASM is actually a small, fast loading binary format that aims to maximize hardware capabilities for native execution efficiency

security

WebAssembly runs in a sandboxed execution environment and can even be implemented in an existing JavaScript virtual machine. In a Web environment, WebAssembly will strictly adhere to the same origin policy and browser security policy.

standard

WebAssembly is designed to be versionless, feature-testable, and backward compatible on the Web. A WebAssembly can be called by JavaScript into a JavaScript context, or it can invoke browser functions like a Web API. Of course, WebAssembly can run in a non-Web environment as well as in a browser.

WebAssembly supports multiple languages

Current high-level languages that can compile into WebAssembly bytecode are:

AssemblyScript: Syntactic with TypeScript, low learning cost for front ends, best choice for front ends to write WebAssembly; C ++: The official recommended way. Rust: Syntax is complex and expensive to learn, which can be difficult for the front-end. Kotlin: The syntax is similar to Java and JS, and the language is cheap to learn. Golang: Grammar is easy and cheap to learn. WebAssembly support is not yet available.

Development environment setup

Install the WebAssembly for Rust environment

Install the Rust

Walk to the www.rust-lang.org/tools/insta… Oh ~

Build tools

To compile Rust into WebAssembly, you need a tool: wASM-pack. You can convert a single command to WebAssembly using wASM-pack. Download and install using the following commands:

bash cargo install wasm-pack

Wasm-pack installation has potholes

There may be a lack of dependencies on Ubuntu

installed libssl-dev on ubuntu 18 and still get this error:
error: failed to run custom build command forOpenssl - sys v0.9.39 process didn't exit successfully: /home/forecast/cs453_finalproj_backend/target/release/build/openssl-sys-864259d0b1f702fc/build-script-main (exit code: 101).Copy the code

You may need to install:

sudo apt install pkg-config
sudo apt install libssl-dev
Copy the code

To write some Rust

The Fibonacci number is taken as an example in this paper

Cargo new –lib hello-wasm-fibonacci package Created by the hello-wasm-fibonacci package

Project Structure:

. ├ ─ ─ Cargo. Toml └ ─ ─ the SRC └ ─ ─ lib. Rs 1 directory, 2 filesCopy the code

Configuration Cargo. Toml

[package]
name = "hello-wasm"
version = "0.1.0 from"
authors = ["Your Name <[email protected]>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
repository = "https://github.com/yourgithubusername/hello-wasm"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
Copy the code

You can finally start writing Rust code

(This article does not expand Rust syntax and focuses on WebAssembly for Rust)

Delete all the original lib.rs code and write whatever you want in it


extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;

// Generate Fibonacci sequence of order n
fn fibonacci(n: u32) - >u32 {
    if n == 0 {
        return 0;
    } else if n == 1 {
        return 1;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2); }}#[wasm_bindgen]
pub fn get_fibonacci(n: u32) - >u32 {
    return fibonacci(n);
}
Copy the code

Do you have a lot of friends?

  • In Rust, libraries are called crates, because we’re using an external library, so extern.
  • use xxx ::nnn::*;Is the use command to introduce code from the library into your code. In this case, the entire module of XXX :: NNN will be introduced
  • The contents in #[] are called “properties” and somehow alter the following statements, similar to Typescript or Java annotations. Using the #[WASM_bindgen] attribute here, you can open up the Rust function to JavaScript.

Package and publish to NPM

Build WebAssembly using WASM-Pack

wasm-pack build --scope mynpmusername

Log in to NPM (NPM installed by default)

npm adduser
Username: yournpmusername
Password:
Email: (this IS public) [email protected]
Copy the code

Access the WebAssembly file directory PKG

cd pkg

Since package.js generated by wASM-pack is missing _bg.js, package.json needs to be modified to supplement it

{
  "name": "@mynpmusername/hello-wasm-fibonacci"."collaborators": [
    "yourgitname <yourgitmail>"]."version": "0.1.0 from"."files": [
    "hello_wasm_fibonacci_bg.wasm"."hello_wasm_fibonacci.js"."hello_wasm_fibonacci_bg.js"."hello_wasm_fibonacci.d.ts"]."module": "hello_wasm_fibonacci.js"."types": "hello_wasm_fibonacci.d.ts"."sideEffects": false
}
Copy the code

Published to the NPM

npm publish –access=public

Used in front-end projects

New Front-end Project

mkdir web

The new package. The json

{
  "scripts": {
    "serve": "webpack-dev-server"
  },
  "dependencies": {
    "@mynpmusername/hello-wasm-fibonacci": "^ 0.1.0 from"
  },
  "devDependencies": {
    "webpack": "^ 4.25.1"."webpack-cli": "^ 3.1.2." "."webpack-dev-server": "^ 3.1.10"}}Copy the code

New webpack. Config. Js

const path = require('path');
module.exports = {
  entry: "./index.js".output: {
    path: path.resolve(__dirname, "dist"),
    filename: "index.js",},mode: "development"
};
Copy the code

index.htm


      
<html>
  <head>
    <meta charset="utf-8">
    <title>hello-wasm example</title>
  </head>
  <body>
    <script src="./index.js"></script>
  </body>
</html>
Copy the code

index.js

const fibonacci = import("./node_modules/@yournpmusername/hello-wasm-fibonacci/hello_wasm_fibonacci.js");

fibonacci.then(fibonacci= > {
  const a = fibonacci.get_fibonacci(10)
  console.log(a)
});
Copy the code

AssemblyScript

Typescript write wasm

  • The official address
  • Implementation method
    • yarn init -y
    • yarn add @assemblyscript/loader
    • yarn add assemblyscript -D
    • npx asinit .
    • yarn
    • yarn asbuild or yarn asbuild:watch
{
    "scripts": {"asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --validate --sourceMap --debug"."asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --validate --sourceMap --optimize"."asbuild": "npm run asbuild:untouched && npm run asbuild:optimized"."asbuild:watch": "onchange -i 'assembly/**/*' -- npm run asbuild"The onchange library is needed to implement the development pattern}}Copy the code

Tsconfig. Json configuration

{
  "extends": ".. /node_modules/assemblyscript/std/assembly.json"."include": [
    "./**/*.ts"]}Copy the code

Development is similar to TS

// The entry file of your WebAssembly module.

export function add(a: i32, b: i32) :i32 {
  return a + b;
}

export function isPrime(x: u32) :bool {
  if (x < 2) {
      return false;
  }

  for (let i: u32 = 2; i < x; i++) {
      if (x % i === 0) {
          return false; }}return true;
}


export function fabonacci(n:number) :number{
  return n < 2 ? n : fabonacci(n - 1) +  fabonacci(n - 2);
}
Copy the code

conclusion

  • TypeScript generates WASM faster than Rust, and Rust packages wASM many times smaller than TypeScrip (more on that next time).
  • The Rust language still needs to be learned
  • Wasm performs much better than JS and can be used in high-performance scenarios.
  • Wasm is now fully packaged for workflow

The Demo

  • DEMO 1
  • DEMO 2

If you can’t be bothered with the environment, you want to try WebAssembly

You can use webassembly.studio/ directly

The author



Benny Shi


Ken.Xu