การเลือกภาษา
ทุก 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/ พร้อม 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 ส่วน 1Password ใช้ Rust คอมไพล์เป็น Wasm สำหรับ Core Cryptography และ Vault Logic ที่รันใน browser ขณะที่ Shopify Functions ให้ Merchant เขียน Custom Checkout Logic ด้วย Rust หรือ AssemblyScript แล้วคอมไพล์เป็น Wasm — สามตัวอย่างที่เลือกภาษาต่างกันตาม Requirement ของตัวเอง