การเลือกภาษา
ทุก Wasm Toolchain มีจุดหมายปลายทางเดียวกัน — ไฟล์ .wasm Binary ที่รันใน browser — แต่แต่ละตัวเดินบนเส้นทางที่ต่างกัน การเลือกที่ถูกต้องขึ้นอยู่กับ Codebase ที่มีอยู่, ทักษะของทีม และข้อจำกัดของโปรเจกต์
ตารางเปรียบเทียบ
หัวข้อที่มีชื่อว่า “ตารางเปรียบเทียบ”| คำถาม | Rust | C / Emscripten | AssemblyScript | TinyGo |
|---|---|---|---|---|
| ทีมเขียนภาษานี้อยู่แล้วหรือ? | บางที | บางที | ถ้ารู้จัก TS | ถ้ารู้จัก Go |
| มี Codebase ที่ต้อง Port หรือ? | ไม่ | ใช่ | ไม่ | ไม่ |
| ขนาด Binary เป็นหลัก? | ยอดเยี่ยม | ใหญ่ (libc overhead) | ยอดเยี่ยม | ดี |
| GC / Runtime Overhead? | ไม่มี | เฉพาะ libc | ไม่มี | น้อยมาก |
| JS Interop ที่สมบูรณ์ (String, Object)? | ใช่ (wasm-bindgen) | ผ่าน ccall/cwrap | ผ่าน Loader | จำกัด |
| ครอบคลุม Standard Library? | ครบถ้วน | ครบถ้วน libc | จำกัด | บางส่วน |
| รองรับ Async / Concurrency? | ผ่าน Futures | ผ่าน Asyncify | จำกัด | จำกัด |
| Learning Curve (เฉพาะ Wasm)? | ปานกลาง | ต่ำ (ถ้ารู้ C) | ต่ำมาก (TS) | ต่ำ (ถ้ารู้ Go) |
Rust — เมื่อใดควรเลือก
หัวข้อที่มีชื่อว่า “Rust — เมื่อใดควรเลือก”เลือก Rust เมื่อคุณ เขียนโค้ด Wasm ใหม่ และต้องการ:
- Binary ที่เล็กที่สุดเท่าที่เป็นไปได้ (ไม่มี GC, ไม่มี Runtime Heap)
- JS Binding ที่ปลอดภัยและอัตโนมัติผ่าน
wasm-bindgen - Crate Ecosystem ที่ออกแบบมาสำหรับ
wasm32-unknown-unknown - แพ็กเกจ npm ที่ Publish ได้จาก
wasm-pack
wasm-pack build --target web# → pkg/ ready to npm publishC / C++ กับ Emscripten — เมื่อใดควรเลือก
หัวข้อที่มีชื่อว่า “C / C++ กับ Emscripten — เมื่อใดควรเลือก”เลือก Emscripten เมื่อคุณ Port ไลบรารี C/C++ ที่มีอยู่ และต้องการ:
printf,malloc, File I/O และ POSIX API ทำงานได้โดยไม่แก้โค้ด- OpenGL Emulation ผ่าน WebGL (
-sUSE_WEBGL2) - Build ขั้นตอนเดียวจาก Makefile หรือ CMake Project ที่มีอยู่
emcc existing_lib.c -o out.js -sEXPORTED_FUNCTIONS='["_my_api"]' -O2AssemblyScript — เมื่อใดควรเลือก
หัวข้อที่มีชื่อว่า “AssemblyScript — เมื่อใดควรเลือก”เลือก AssemblyScript เมื่อทีมของคุณ เขียน TypeScript และต้องการ:
- Learning Curve ที่ต่ำมาก (Syntax เดิม แค่ Numeric Type ต่างกัน)
- Wasm Module เล็กและ Self-contained โดยไม่มี Dependency
- วน Iteration เร็วโดยไม่ต้องตั้งค่า Rust หรือ C Toolchain
npx asc assembly/index.ts --outFile build/release.wasm --optimizeTinyGo — เมื่อใดควรเลือก
หัวข้อที่มีชื่อว่า “TinyGo — เมื่อใดควรเลือก”เลือก TinyGo เมื่อทีมของคุณ เขียน Go และต้องการแชร์แพ็กเกจ Pure Logic ระหว่าง Go Backend กับ Browser Frontend:
tinygo build -o wasm.wasm -target wasm ./main.goหมายเหตุ: TinyGo ไม่รองรับ Go Standard Library ทั้งหมด แพ็กเกจที่ใช้ net, os หรือ Reflection อาจคอมไพล์ไม่ได้ ตรวจสอบ ตาราง Package Support ของ TinyGo ก่อนตัดสินใจ
Flowchart การตัดสินใจ
หัวข้อที่มีชื่อว่า “Flowchart การตัดสินใจ”- มีโค้ด C/C++ ที่ทำงานได้อยู่แล้วหรือ? → Emscripten
- ทีมเขียน TypeScript และต้องการเริ่มต้นเร็ว? → AssemblyScript
- ทีมเขียน Go หรือ? → TinyGo
- เขียนโค้ดใหม่และต้องการขนาด Binary ที่ดีที่สุดพร้อม JS Interop? → Rust
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Rust + wasm-bindgen | Memory Safety จาก Ownership Model และ Binary Size เล็กมาก ไม่มี GC | Learning Curve สูงกว่าตัวอื่นเพราะต้องเข้าใจ Ownership/Borrowing |
| C/C++ + Emscripten | Ecosystem C/C++ มหาศาล Port Codebase เดิมได้เกือบทันที | Glue Code และ POSIX Emulation Layer เพิ่ม Runtime Overhead ทำให้ Binary ใหญ่ |
| AssemblyScript | Syntax คุ้นเคยสำหรับทีม TypeScript เริ่มต้นได้เร็วที่สุด | Ecosystem จำกัดมาก และ ไม่ semantically เหมือน TypeScript ทุกจุด — Type System ต่างกัน |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- เลือกภาษาตามความถนัดของทีมอย่างเดียวโดยไม่ดู Binary Size ที่ตามมา เช่น ใช้ Emscripten สำหรับ Module เล็กๆ ที่ไม่มี Codebase เดิมให้ Port ทำให้ Ship Runtime ใหญ่เกินจำเป็น
- Ship Emscripten Build แบบไม่ Optimise — ไม่ Strip POSIX Emulation Layer และไม่ใช้ Flag อย่าง
-O3หรือ-sMINIMAL_RUNTIMEจน Bundle บวม - คิดว่า AssemblyScript คือ TypeScript ทั้งหมด แล้วใช้ Syntax หรือ Semantics ที่
ascไม่รองรับ จนเจอ Compile Error หรือ Bug แปลกๆ ที่ตามหายาก
💡 ตัวอย่างจากของจริง
Figma เลือก C++ กับ Emscripten สำหรับ Rendering Engine ที่ Port มาจาก Desktop และวัดผลได้ว่าเวลาโหลด เร็วขึ้นมากกว่า 3 เท่า หลังเปลี่ยนมาใช้ Wasm (Figma engineering blog) ในทางกลับกัน Shopify Functions ให้ Merchant เขียน Custom Checkout Logic ที่คอมไพล์เป็น Wasm ได้ — ปัจจุบันรองรับ Rust หรือ JavaScript (เอกสาร Shopify Functions) — สองตัวอย่างที่เลือกภาษาต่างกันตาม Requirement ของตัวเอง