ทดลอง Compile Rust เป็น WebAssembly
สืบเนื่องจากช่วงนี้ผมสนใจ WebAssembly เป็นพิเศษ เนื่องจากสนใจ Rust ด้วย และคิดว่ามันก็น่าสนใจ และมักจะเห็นคนพูดถึงสองตัวนี้บ่อยๆ ก็เลยพยายามศึกษาเรื่อยๆ เวลาว่างๆ เอาจริงๆ ก็ยังไม่ค่อยรู้อะไรเท่าไหร่ เน้นอ่าน ลองเล่น เข้าใจบ้าง ไม่เข้าใจบ้าง วันนี้ก็เลยมาเขียนบล็อกบันทึกเอาไว้ซะหน่อย
WebAssembly คืออะไร?
WebAssembly หรือ WASM คือ low level bytecode ที่รันบนเว็บ โดยเขียนได้หลายภาษา (ที่รองรับการ compile เป็น WASM) เช่น C/C++ หรือ Rust ตัว concept WASM คือเป็น binary format ที่สามารถทำงานร่วมกับ JavaScript ได้ และปัจจุบัน WASM ก็รองรับ Browser หลักๆ เกือบหมดแล้ว
เริ่มต้น WebAssembly
เริ่มจาก Getting Started จากเว็บ Official เลย จากนั้น ก็เลือกภาษา Rust ตัว Tutorial ก็จะเป็นของ Mozilla Developer
เราสามารถใช้ Rust และ WebAseembly ร่วมกันได้ แบบ 2 use cases ใหญ่ๆ คือ
- เขียนทั้งแอพด้วย Rust แล้ว compile เป็น WASM
- เขียนด้วย Rust แค่บางส่วน แล้วใช้ร่วมกับ JavaScript frontend ก็ได้
ตัว Rust/Wasm Framework ชื่อ yew เป็นอีกตัวที่ผมสนใจ เพราะดูคล้ายๆ React + Elm อยู่ใน list ที่ว่าจะลองศึกษาดู
Create Project
- ติดตั้ง Rust
เริ่มต้น Install Rust ด้วย rustup - หากไม่เคยติดตั้ง แนะนำ อ่านเพิ่มเติม มาหัดเขียนโปรแกรมด้วยภาษา Rust กันเถอะ
- ติดตั้ง wasm-pack - เป็นตัวช่วยที่ให้เรา build ไฟล์ Rust เป็น WASM รวมถึง build package ที่สามารถไปรันบน Browser ได้เลย
cargo install wasm-pack- สร้าง folder ใหม่ ชื่อ
hello-wasm
cargo new --lib hello-wasmจะมีไฟล์ในโฟลเดอร์ hello-wasm แบบนี้
├── Cargo.toml└── src └── lib.rs
1 directory, 2 filesเพิ่ม wasm-bindgen ใน Cargo.toml และ [lib]
[lib]crate-type = ["cdylib", "rlib"]
[dependencies]wasm-bindgen = "0.2.80"แนะนำ Rust Analyzer เป็น VS Code Extension สำหรับเขียนภาษา Rust
- Update
lib.rsเป็นโค๊ดที่ใช้wasm_bindgen(ใช้สำหรับเขียน Rust กับ JavaScript เช่น Rust เรียก function JavaScript หรือ JS เรียก Rust ได้)
use wasm_bindgen::prelude::*;
#[wasm_bindgen]extern { pub fn alert(s: &str);}
#[wasm_bindgen]pub fn greet(name: &str) { alert(&format!("Hello, {}!", name));}จากโค๊ดนี้เราสามารถเรียก alert() ที่เป็น JavaScript function จาก Rust ได้
- Compile โปรแกรมดู เพื่อ compile จาก Rust เป็น WebAssembly
wasm-pack build --target webจะได้ผลลัพธ์ประมาณนี้
[WARN]: ⚠️ origin crate has no README[INFO]: ⬇️ Installing wasm-bindgen...[INFO]: found wasm-opt at "/opt/homebrew/bin/wasm-opt"[INFO]: Optimizing wasm binaries with `wasm-opt`...[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended[INFO]: ✨ Done in 5.49s[INFO]: 📦 Your wasm pkg is ready to publish at /dev/hello-wasm/pkg.เราจะได้โฟลเดอร์ pkg ข้างในมี WASM และไฟล์ JavaScript ที่เราสามารถเอาไปใช้บนเว็บได้เลย
WASM on Web
ตัวอย่าง ลองสร้างไฟล์ index.html ง่ายๆ ขึ้นมา
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Hello WASM</title> </head> <body> <script type="module"> import init, { greet } from './pkg/hello_wasm.js'
init().then(() => { greet('WebAssembly') }) </script> </body></html>