add wasm
This commit is contained in:
parent
26d0ad54f6
commit
a497c60af9
1 changed files with 178 additions and 0 deletions
178
technology/dev/WebAssembly.md
Normal file
178
technology/dev/WebAssembly.md
Normal file
|
@ -0,0 +1,178 @@
|
|||
---
|
||||
obj: concept
|
||||
mime: application/wasm
|
||||
extension: wasm
|
||||
website: https://webassembly.org
|
||||
rev: 2024-03-26
|
||||
---
|
||||
|
||||
# WebAssembly
|
||||
WebAssembly, often abbreviated as Wasm, is an open standard and binary instruction format designed for a stack-based virtual machine. It aims to execute code efficiently across various platforms, including web browsers. WebAssembly is a portable binary instruction format that serves as a compilation target for high-level programming languages like C, C++, and [Rust](programming/languages/Rust.md). It enables these languages to be executed in web browsers at near-native speeds, bridging the performance gap between web applications and native applications.
|
||||
|
||||
## Features of WebAssembly
|
||||
### 1. **Efficiency**
|
||||
- WebAssembly binaries are designed to be compact and fast to load, enabling efficient transmission over the network.
|
||||
- It leverages Just-In-Time (JIT) compilation techniques for optimal runtime performance.
|
||||
|
||||
### 2. **Safety**
|
||||
- WebAssembly runs in a sandboxed environment within the browser, providing a high level of security.
|
||||
- It uses a memory-safe, sandboxed execution model to prevent malicious code from compromising the host environment.
|
||||
|
||||
### 3. **Compatibility**
|
||||
- WebAssembly is designed to be platform-independent, allowing code to run consistently across different architectures and operating systems.
|
||||
- It integrates seamlessly with existing web technologies like JavaScript, enabling interoperability with web applications.
|
||||
|
||||
### 4. **Versatility**
|
||||
- WebAssembly can be used for a variety of use cases beyond web development, including server-side applications, game engines, and multimedia processing.
|
||||
|
||||
## How WebAssembly Works
|
||||
|
||||
WebAssembly code is typically generated by compiling source code written in languages like C, C++, or [Rust](programming/languages/Rust.md) using specific compilers such as Emscripten or the [Rust](programming/languages/Rust.md) compiler with the `wasm32-unknown-unknown` target.
|
||||
|
||||
Once compiled, the WebAssembly code can be executed within a web browser using the JavaScript-based WebAssembly runtime. Alternatively, it can be run outside the browser using standalone WebAssembly runtimes or integrated into existing software systems.
|
||||
|
||||
## Use Cases of WebAssembly
|
||||
WebAssembly has various applications across different domains:
|
||||
- **Web Development**: Enhancing web applications with high-performance computations, multimedia processing, and gaming.
|
||||
- **Server-Side Applications**: Running compute-intensive tasks efficiently on the server.
|
||||
- **Game Development**: Building cross-platform games with near-native performance.
|
||||
- **Multimedia Processing**: Processing and manipulating multimedia content such as images, audio, and video in the browser.
|
||||
- **Blockchain**: Executing smart contracts and decentralized applications (DApps) on blockchain platforms.
|
||||
|
||||
|
||||
## Usage with [Rust](programming/languages/Rust.md)
|
||||
### Requirements
|
||||
You need [Rust](programming/languages/Rust.md) installed and the following for creating the WebAssembly:
|
||||
```sh
|
||||
cargo install wasm-pack
|
||||
```
|
||||
|
||||
### Creating the project
|
||||
Create a new library:
|
||||
```sh
|
||||
cargo new --lib hello-wasm
|
||||
```
|
||||
|
||||
Sample `src/lib.rs`:
|
||||
```rust
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
pub fn alert(s: &str);
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn greet(name: &str) {
|
||||
alert(&format!("Hello, {}!", name));
|
||||
}
|
||||
```
|
||||
|
||||
wasm-pack uses wasm-bindgen, another tool, to provide a bridge between the types of JavaScript and [Rust](programming/languages/Rust.md). It allows JavaScript to call a [Rust](programming/languages/Rust.md) API with a string, or a [Rust](programming/languages/Rust.md) function to catch a JavaScript exception.
|
||||
|
||||
### Calling external functions in JavaScript from [Rust](programming/languages/Rust.md)
|
||||
```rust
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
pub fn alert(s: &str);
|
||||
}
|
||||
```
|
||||
|
||||
As you might suspect, this is the alert function provided by JavaScript.
|
||||
|
||||
Whenever you want to call JavaScript functions, you can add them to this file, and wasm-bindgen takes care of setting everything up for you. Not everything is supported yet, but we're working on it.
|
||||
|
||||
### Producing [Rust](programming/languages/Rust.md) functions that JavaScript can call
|
||||
```rust
|
||||
#[wasm_bindgen]
|
||||
pub fn greet(name: &str) {
|
||||
alert(&format!("Hello, {}!", name));
|
||||
}
|
||||
```
|
||||
|
||||
Once again, we see the `#[wasm_bindgen]` attribute. In this case, it's not modifying an `extern` block, but a `fn`; this means that we want this [Rust](programming/languages/Rust.md) function to be able to be called by JavaScript. It's the opposite of `extern`: these aren't the functions we need, but rather the functions we're giving out to the world.
|
||||
|
||||
This function is named `greet`, and takes one argument, a string (written `&str`), `name`. It then calls the `alert` function we asked for in the `extern` block above.
|
||||
|
||||
### Compiling our code to WebAssembly
|
||||
To compile our code correctly, we first need to configure it with `Cargo.toml`. Open this file, and change its contents to look like this:
|
||||
```toml
|
||||
[package]
|
||||
name = "hello-wasm"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
description = "A sample project with wasm-pack"
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/yourgithubusername/hello-wasm"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
```
|
||||
|
||||
The big part to add is the `[package]`. The `[lib]` part tells [Rust](programming/languages/Rust.md) to build a `cdylib` version of our package.
|
||||
The last section is the `[dependencies]` section. Here's where we tell [Cargo](../applications/development/cargo.md) what version of `wasm-bindgen` we want to depend on.
|
||||
|
||||
### Building the package
|
||||
Now that we've got everything set up, let's build the package. We'll be using the generated code in a native ES module and in Node.js. For this purpose, we'll use the `--target` argument in `wasm-pack build` to specify what kind of WebAssembly and JavaScript is generated.
|
||||
|
||||
```sh
|
||||
wasm-pack build --target web
|
||||
```
|
||||
|
||||
This does a number of things (and they take a lot of time, especially the first time you run `wasm-pack`). In short, `wasm-pack build`:
|
||||
- Compiles your [Rust](programming/languages/Rust.md) code to WebAssembly.
|
||||
- Runs `wasm-bindgen` on that WebAssembly, generating a JavaScript file that wraps up that WebAssembly file into a module the browser can understand.
|
||||
- Creates a `pkg` directory and moves that JavaScript file and your WebAssembly code into it.
|
||||
- Reads your `Cargo.toml` and produces an equivalent `package.json`.
|
||||
- Copies your `README.md` (if you have one) into the package.
|
||||
|
||||
### Using the package on the web
|
||||
Now that we've got a compiled Wasm module, let's run it in the browser. Let's start by creating a file named `index.html` in the root of the project, so we end up with the following project structure:
|
||||
```
|
||||
├── Cargo.lock
|
||||
├── Cargo.toml
|
||||
├── index.html <-- new index.html file
|
||||
├── pkg
|
||||
│ ├── hello_wasm.d.ts
|
||||
│ ├── hello_wasm.js
|
||||
│ ├── hello_wasm_bg.wasm
|
||||
│ ├── hello_wasm_bg.wasm.d.ts
|
||||
│ └── package.json
|
||||
├── src
|
||||
│ └── lib.rs
|
||||
└── target
|
||||
├── CACHEDIR.TAG
|
||||
├── release
|
||||
└── wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
Put the following content in the `index.html` file:
|
||||
```html
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>hello-wasm example</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
import init, { greet } from "./pkg/hello_wasm.js";
|
||||
init().then(() => {
|
||||
greet("WebAssembly");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The script in this file will import the JavaScript glue code, initialize the Wasm module, and call the `greet` function we wrote in [Rust](programming/languages/Rust.md).
|
||||
|
||||
Serve the root directory of the project with a local web server, (e.g. `python3 -m http.server`).
|
||||
|
||||
> Note: Make sure to use an up-to-date web server that supports the `application/wasm` [MIME](../files/MIME.md) type. Older web servers might not support it yet.
|
||||
|
||||
Load `index.html` from the web server. An alert box appears on the screen, with `Hello, WebAssembly!` in it. We've successfully called from JavaScript into [Rust](programming/languages/Rust.md), and from [Rust](programming/languages/Rust.md) into JavaScript.
|
Loading…
Reference in a new issue