What is Wasm?

The official MDN document defines it as follows

WebAssembly(for ease of writing, Wasm) is a new form of coding that can be run in modern web browsers – it is a low-level, class-like assembly language with a compact binary format that can be run at near-native performance and provides a compilation target for languages such as C/C ++. So that they can run on the Web. It is also designed to coexist with JavaScript, allowing the two to work together.

For Web platforms, WebAssembly makes huge sense — it provides a way for code written in a variety of languages to run on the Web at near-native speeds. In this case, any client software that could not previously run this way will be able to run on the Web.

WebAssembly is designed to work with JavaScript — by using WebAssembly’s JavaScript API, you can load WebAssembly modules into a JavaScript application and share functionality between the two. This allows you to leverage the performance and power of WebAssembly and the expressiveness and flexibility of JavaScript in the same application, even if you may not know how to write WebAssembly code.


In the opening words of “introduction to WebAssembly” written by Mr. Yu hang, the teacher summed up “WebAssembly ISA virtual binary instruction set (v-isa) based on a stack virtual machine, which is designed as a portable compilation target for high-level programming languages”.

With curiosity, we started our Wasm learning path and created our first Wasm application.

Environmental installation

Rust

A language that empowers everyone to build reliable and efficient software.

  • The installation
# macOS
curl --proto '=https'- tlsv1.2 - sSf https://sh.rustup.rs | sh# Other installation methods
# https://forge.rust-lang.org/infra/other-installation-methods.html
Copy the code
  • The command
# Version update
rustup update

# View version
cargo --version

# Build project
cargo build

# Run the project
cargo run

# Test project
cargo test

# Build documentation for the project
cargo doc

Publish the library to crates. IO
cargo publish
Copy the code
# nightly rust
rustup toolchain install nightly

rustup toolchain list

rustup override set nightly
Copy the code

Node.js

Node.js is a JavaScript runtime built on Chrome’s V8 JavaScript engine

wasm-pack

Used to build and use Rust generated WebAssembly that you want to interoperate with JavaScript, browsers, or Node.js.

  • The installation
# macOS
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# Other installation methods
# https://rustwasm.github.io/wasm-pack/installer
Copy the code
  • The command
# to create
# https://rustwasm.github.io/docs/wasm-pack/commands/new.html
wasm-pack new <name> --template <template> --mode <normal|noinstall|force>

# building
# https://rustwasm.github.io/docs/wasm-pack/commands/build.html
wasm-pack build
  [--out-dir <out>]
  [--out-name <name>]
  [--<dev|profiling|release>]
  [--target <bundler|nodejs|web|no-modules>]
  [--scope <scope>]
  [mode <normal|no-install>]

# test
# https://rustwasm.github.io/docs/wasm-pack/commands/test.html
wasm-pack test

# contract
# https://rustwasm.github.io/docs/wasm-pack/commands/pack-and-publish.html
# npm pack
wasm-pack pack
# npm publish
wasm-pack publish
Copy the code

Vite

Next generation front-end tools

  • Vite-plugin-rsw: The Vite plug-in integrates with the WASM-Pack for hot updates and builds
# vite project install
npm i -D vite-plugin-rsw
# or
yarn add -D vite-plugin-rsw
Copy the code

Quick start

  • In the originalviteProject, just install the configurationvite-plugin-rswPlugins will do.
  • New projects are availableviteTo provide the@vitejs/appInitialize the project, and then install the configurationvite-plugin-rsw.
  • My scaffolding is recommended for new projectscreate-xc-app, and periodically update and maintain related version dependencies.

create-xc-app

⚡️ Create a project in seconds! Maintains a variety of front-end project templates based on Vite, deno, etc.

npx create-xc-app my-wasm-app --template wasm-react
Copy the code

Create Wasm package

# Two ways
# name If you start with @ to create the NPM organization package
# will be converted to a hyphen, you need to manually change the folder name
wasm-pack new <name>
# or
# name can be an NPM organization
Cargo new -- lib@rsw /hello
# Need to configure Cargo. Toml manually
cargo new --lib <name>
Copy the code

The project structure

# Recommended directory structure
[my-wasm-app] # Project root path
|- [rust-crate] # NPM package ` rust - crate `
|    |- [pkg] The directory where the wASM package is generated
|    |- [src] # rust source code
|    | # learn more: https://doc.rust-lang.org/cargo/reference/cargo-targets.html
|    |- [target] # Project dependencies, similar to NPM's 'node_modules'
|    | # learn more: https://doc.rust-lang.org/cargo/reference/manifest.html
|    |- Cargo.toml # rust Package management list
|    `- ...
|- [@rsw] # NPM Organization package
|     |- [hello] # @rsw/hello, directory structure as' rust-crate '
|     `- ...
|- [node_modules] # Front-end project package dependencies
|- [src] # Front-end source code (can be vue, React, or other)
| # learn more: https://nodejs.dev/learn/the-package-json-guide
|- package.json # 'NPM' or 'yarn' package management list
| # learn more: https://vitejs.dev/config
|- vite.config.ts # vite configuration file
| # learn more: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
|- tsconfig.json # vite configuration file`...Copy the code

At first glance, this directory may seem a bit complicated, but it is actually a standard Vite based front-end project. Then, add the wASM package we need to build under the root path. (A Rust Crate will generate a wASM package that can be published separately to NPM.)

Project configuration

Step1: vite.config.ts

// Take the React project as an example
import reactRefresh from '@vitejs/plugin-react-refresh';
import { defineConfig } from 'vite';
import ViteRsw from 'vite-plugin-rsw';

export default defineConfig({
  plugins: [
    reactRefresh(),
    More configuration: / / https://github.com/lencx/vite-plugin-rsw
    ViteRsw({
      // Includes production and development modes
      mode: 'release'.crates: [
        // Package name, support NPM organization
        '@rsw/hello']}),],})Copy the code

Step2: rust-crate/Cargo.toml

#...

[lib]
# https://doc.rust-lang.org/reference/linkage.html
crate-type = ["cdylib"]
wasm-opt = false

# https://doc.rust-lang.org/cargo/reference/profiles.html
# dev | release | test | bench
[profile.release]
lto = true
opt-level = "s"

# https://doc.rust-lang.org/cargo/guide/dependencies.html
# specify dependencies: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
Dependencies and versioning, similar to NPM's 'package.json'
[dependencies]
wasm-bindgen = "0.2.69"
Copy the code

Step3: rust-crate/src/lib.rs

use wasm_bindgen::prelude::*;

// Import the `window.alert` function from the Web.
#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

// Export a `greet` function from Rust to JavaScript, that alerts a hello message.
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
Copy the code

Step4: src/App.tsx

// src/App.tsx

import React, { useEffect } from 'react';
import init, { greet } from 'wasm-test';

import logo from './logo.svg';
import './App.css';

function App() {
  useEffect(() = > {
    // WASM is initialized when the 'wasm-test' package method is called
    // You must first ensure that the initialization has been performed, otherwise an error will be reported
    // If multiple WASM packages exist, each wASM package must be initialized
    init();
  }, [])

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>Hello WebAssembly!</p>
        <p>Vite + Rust + React</p>
        <p>{/* call the greet method */}<button onClick={()= > greet('wasm')}>hi wasm</button>
        </p>
        <p>Edit <code>App.tsx</code> and save to test HMR updates.</p>
      </header>
    </div>)}export default App
Copy the code

Complete code example

Source: github.com/lencx/learn…

At this point, the wASM project setup is complete, and now it’s time for your imagination.

Technical communication

To facilitate communication and learning of WASM, I created a WASM wechat communication group, you can scan the below TWO-DIMENSIONAL code, two-dimensional code expired or cannot join, you can follow the public account “Float static”, send to the group, I will pull you into the group to learn and progress together.

A link to the

  • vite: vitejs.dev
  • nodejs: nodejs.org
  • rust: www.rust-lang.org
  • webassembly: webassembly.org
  • rsw: Github.com/lencx/vite-…
  • wasm-pack: rustwasm.github.io/wasm-pack
  • rust-to-wasm: Developer.mozilla.org/en-US/docs/…
  • wasm-bindgen: Github.com/rustwasm/wa…
  • learn-wasm: Github.com/lencx/learn…