14 คะแนน โดย GN⁺ 2025-02-26 | 6 ความคิดเห็น | แชร์ทาง WhatsApp
  • พร้อมกับการเปิดตัว Dagger Cloud v3 ทาง Dagger ได้เขียน UI ใหม่ด้วย WebAssembly(WASM) และ Go
  • โดยทั่วไป Go ไม่ค่อยถูกใช้สำหรับพัฒนาเว็บ UI แต่เลือกแนวทางนี้เพื่อ "รวมโค้ดเบสและปรับจูนประสิทธิภาพ"
  • บทความนี้แบ่งปัน "เบื้องหลังการตัดสินใจ ความท้าทายระหว่างการพัฒนา และผลลัพธ์สุดท้าย"

ปัญหาเดิม: ความไม่มีประสิทธิภาพจากการมีโค้ดเบสสองชุด

  • Dagger ทำงานบนพื้นฐานของ DAG(Directed Acyclic Graph) และแสดงผลภาพผ่านทั้ง TUI(เทอร์มินัล UI) และ เว็บแดชบอร์ด(Dagger Cloud)
  • เดิมที TUI พัฒนาด้วย Go ส่วนเว็บ UI พัฒนาด้วย React/TypeScript
  • แต่การซิงก์ระหว่าง UI ทั้งสองทำได้ยาก และโดยเฉพาะเว็บ UI มีปัญหาด้านประสิทธิภาพเมื่อต้องประมวลผลข้อมูลจำนวนมากแบบเรียลไทม์
  • ระหว่างจัดการสตรีมอีเวนต์ OpenTelemetry ที่ซับซ้อนซึ่งมีสแปนหลายแสนรายการ ประสิทธิภาพและความเร็วของ React UI ลดลงอย่างชัดเจน
  • ต้องพัฒนาฟังก์ชันเดียวกันซ้ำสองครั้ง ซึ่งเป็น ภาระการพัฒนาที่หนักสำหรับทีมขนาดเล็ก
  • ดังนั้นจึงเริ่มมองหาแนวทางใหม่โดยมีเป้าหมายคือ รวมโค้ดเบสและปรับปรุงประสิทธิภาพ

ทางออกที่เลือก: Go + WebAssembly

  • รวมโค้ดเบสด้วย Go
    • เนื่องจาก TUI ถูกพัฒนาด้วย Go อยู่แล้ว หากเว็บ UI ก็พัฒนาด้วย Go ก็จะสามารถนำโค้ดกลับมาใช้ซ้ำได้
    • ในทีมมีนักพัฒนา Go จำนวนมาก จึงช่วย เพิ่มประสิทธิภาพการทำงานของทีมและทำให้ดูแลรักษาได้ง่ายขึ้น
  • ใช้ WebAssembly(WASM)
    • นำ WebAssembly มาใช้เพื่อให้สามารถรันโค้ด Go ในเบราว์เซอร์ได้โดยตรง
    • อย่างไรก็ตาม Go + WASM ยังมีระบบนิเวศที่ไม่สุกงอมเต็มที่ จึงมีความท้าทายอยู่บ้าง:
      • ไลบรารีคอมโพเนนต์มีน้อย → ต้องสร้าง UI เอง
      • ข้อจำกัดหน่วยความจำ WASM ของเบราว์เซอร์ (2GB) → ต้องปรับจูนเมื่อจัดการข้อมูลปริมาณมาก
      • แต่การปรับจูนหน่วยความจำก็สามารถเป็นประโยชน์ได้ทั้งกับ TUI และเว็บ UI

กลยุทธ์ลดความเสี่ยงของโปรเจ็กต์

  • ใช้เฟรมเวิร์ก Go-app
    • เลือกเฟรมเวิร์กที่พัฒนาด้วย Go สำหรับการสร้าง PWA(Progressive Web App)
    • ให้โมเดลแบบคอมโพเนนต์คล้าย React จึงย้ายมาใช้งานได้ไม่ยาก
  • สร้างและตรวจสอบโปรโตไทป์
    • นำ UI เดิมมาสร้างใหม่ด้วย Go-app ให้มากที่สุดเพื่อระบุประเด็นสำคัญ
    • WASM เป็นมาตรฐานเปิดที่มีเอกสารรองรับอยู่แล้ว และคำถามหลักส่วนใหญ่หาคำตอบได้จากเอกสารของ Go-app
    • ปัญหาใหญ่ที่สุดคือข้อจำกัดด้านการใช้หน่วยความจำ ซึ่งต้องอาศัยการออกแบบและการปรับจูนเพื่อแก้ไข

ขั้นตอนเปลี่ยนจากโปรโตไทป์สู่โปรดักชัน

กลยุทธ์การปรับจูนประสิทธิภาพ

  • ปรับจูนการเรนเดอร์ล็อกขนาดใหญ่
    • เมื่อต้องจัดการข้อมูลล็อกมากกว่า 200,000 บรรทัด จำเป็นต้องปรับปรุงประสิทธิภาพการเรนเดอร์
    • เพื่อสิ่งนี้จึงปรับจูนไลบรารีเรนเดอร์เทอร์มินัลเสมือน(midterm)
      → ทำให้ทั้ง TUI และเว็บ UI เร็วขึ้น
  • เพิ่มความเร็วในการพาร์ส JSON
    • Go WASM พาร์ส JSON ได้ช้า → จึงออกแบบสมาร์ตแบ็กเอนด์ที่ทำงานบน WebSocket
    • ใช้ encoding/gob ของ Go เพื่อปรับจูนการส่งข้อมูล
  • ปรับขนาดไฟล์ WASM
    • ขนาดไฟล์ WASM เริ่มต้น: 32MB
    • ใช้การบีบอัด Brotli → ลดลงเหลือ 4.6MB
    • เนื่องจาก CDN จัดการการบีบอัดได้ยาก จึงบีบอัดโดยตรงในกระบวนการบิลด์

การปรับปรุงอื่น ๆ

  • นอกจากปัญหาหน่วยความจำที่คาดไว้แล้ว ความกังวลส่วนใหญ่กลายเป็นเรื่องเกินจริง
  • การเขียน UI คอมโพเนนต์ไม่ได้ยาก และ การเชื่อมต่อกับบริการอื่น ๆ (Tailwind, Auth0 ฯลฯ) ก็ไม่มีปัญหา
  • สามารถใช้แพ็กเกจ NPM จากใน WebAssembly ได้ → ทำงานร่วมกับ JavaScript ได้
  • Go-app มีความยืดหยุ่นในการอัปเดตคอมโพเนนต์มากกว่า React ทำให้มีอิสระในการปรับจูนมากกว่า
  • สามารถวิเคราะห์ประสิทธิภาพได้ด้วยเครื่องมือโปรไฟล์ของ Go(pprof) และโปรไฟเลอร์ในตัวของเบราว์เซอร์
  • ด้วย การรองรับ PWA จึง รันเป็นแอปเดสก์ท็อป/มือถือได้ และเปิดใช้งานแอปได้โดยไม่ต้องเปิดเบราว์เซอร์

ข้อดีที่ได้หลังการเปลี่ยนผ่าน

  • ความสม่ำเสมอของ UI ดีขึ้น
    • เมื่อ TUI และเว็บ UI ใช้โค้ดเบสเดียวกัน จึงมอบ UX ที่สอดคล้องกันมากขึ้น
  • ประสิทธิภาพและการใช้หน่วยความจำดีขึ้น
    • เมื่อต้องจัดการข้อมูลจำนวนมาก ความเร็วในการเรนเดอร์ดีขึ้นและใช้หน่วยความจำน้อยลง
  • ประสิทธิภาพการทำงานของทีมสูงขึ้น
    • เดิมทีต้อง ปรับจูนเว็บ UI และ TUI แยกกัน
      ตอนนี้ ปรับจูนครั้งเดียวแล้วใช้ได้กับทั้งสองอินเทอร์เฟซพร้อมกัน
    • ส่งผลให้ โฟกัสกับการพัฒนาฟีเจอร์ใหม่ได้มากขึ้น

ควรเปลี่ยนมาใช้ Go + WASM หรือไม่?

  • โดยทั่วไปไม่แนะนำ แต่ในบางเงื่อนไขอาจมีประโยชน์:
    • ทีมที่มีนักพัฒนา Go จำนวนมาก
    • UI ที่ซับซ้อนและ TypeScript/React เริ่มติดข้อจำกัดด้านประสิทธิภาพ
    • ต้องการแชร์โค้ดระหว่าง TUI และเว็บ UI
    • อยู่ในสภาพแวดล้อมที่ต้องเร่งความเร็วการพัฒนาให้สูงสุด
  • หากตรงกับเงื่อนไขข้างต้น Go + WASM อาจเป็นทางเลือกที่ดี
    อย่างไรก็ตาม ในกรณีส่วนใหญ่เทคโนโลยีเว็บแบบเดิม(React, TypeScript ฯลฯ) ยังเหมาะสมกว่า

6 ความคิดเห็น

 
minho2da 2025-02-27

เหมือน GWT สมัยก่อนหรือเปล่าครับ?

 
bbulbum 2025-02-26

อืม... ก็สงสัยอยู่ว่ามันจะทำให้การพัฒนาที่ปลอดภัยด้านชนิดข้อมูลมากกว่า TS หรือเปล่า

 
colus001 2025-02-26

ไม่ว่าจะมองยังไง ก็เหมือนกำลังทำโจทย์ง่าย ๆ ให้ยากขึ้น...

 
riki3 2025-02-26

การทำฟรอนต์เอนด์ด้วย Go มีประสิทธิภาพกว่าที่คิด เห็นได้ชัดว่าเหตุผลที่กรณีการใช้งานเพิ่มขึ้นนั้นมีอยู่จริง

 
halfenif 2025-02-26

แต่ก็ยังอยากลองทำดูนะ

 
GN⁺ 2025-02-26
ความคิดเห็นจาก Hacker News
  • มีความเห็นว่าทีมขนาดเล็กจำเป็นต้องปล่อยใช้งานให้เร็ว

    • แต่ก็มีการบอกว่าใช้เวลาเกือบหนึ่งเดือนในการทำต้นแบบ ต้องเขียน UI component ของ Go-app เอง และสถาปัตยกรรมก็เปลี่ยนไปมากเพราะ Go WASM ทำการ parse JSON ได้ช้า
    • มีความเห็นว่านี่ฟังดูเหมือนการเขียนโปรแกรมเพื่อใส่ในเรซูเม่มากกว่า
  • พวกเขามีทีมวิศวกร Go ที่แข็งแกร่ง และมี UI ที่ซับซ้อนซึ่งขยายต่อด้วย TypeScript/React ได้ยาก

    • จากเดโมทำให้รู้สึกว่าทีมยังขาดประสบการณ์ด้านเว็บฟรอนต์เอนด์
    • หน้าสมัครสมาชิกไม่พอดีกับหน้าจอ และเมื่อคลิกในแดชบอร์ดจะมี spinner เต็มหน้าจอขึ้นมาแล้วหน้ารีโหลดใหม่
    • ระหว่างที่ไอคอนกำลังโหลด มี alt-text แสดงออกมา
    • มีความเห็นว่านับว่าโชคดีที่ React ไม่ได้เป็นตัวที่ขยายต่อไม่ไหว
  • มีความกังวลว่าอาจเป็นเฟรมเวิร์กที่ "render ลง canvas" แต่จริง ๆ ไม่ใช่

    • เป็นสัญญาณที่ดีว่าการทำงานร่วมกันระหว่าง WASM และ DOM เร็วพอแล้ว
    • แต่ไบนารีขนาด 32MB ก็เป็นข้อเสียใหญ่
  • พวกเขาตัดสินใจใช้ <a href="https://go-app.dev/" rel="nofollow">https://go-app.dev/</a>; เพื่อสร้างฟรอนต์เอนด์

    • Go-app เป็นแพ็กเกจสำหรับสร้าง PWA ด้วย Golang และ WebAssembly
  • มีความเห็นว่า Go ไม่เหมาะกับงานลักษณะนี้

    • ระบุว่าใช้ Rust แล้วได้ผลลัพธ์ที่ดีกว่า
    • ไบนารี wasm ที่สร้างด้วย Rust มีขนาดเฉลี่ย 240kb และบีบอัดได้ดีเมื่อส่งผ่านเครือข่าย
  • คงน่าสนใจถ้ามีรายงานติดตามผลในอีกไม่กี่เดือนว่า การย้ายจากสแตกที่หนักกว่าไปสู่สแตกที่ประสิทธิภาพดีกว่าแต่ค่อนข้างแปลกนั้นให้ผลเชิงบวกหรือไม่

    • การจ้างนักพัฒนาฟรอนต์เอนด์สำหรับโปรเจกต์แบบนี้คงไม่ง่ายไปกว่าการหานักพัฒนา React
  • ผู้สร้าง go-app มาเจอโพสต์นี้เข้าและรู้สึกประหลาดใจ พร้อมอวยพรให้ผลิตภัณฑ์ประสบความสำเร็จ

  • Go WASM parse JSON ได้ช้าจนทำให้ต้องเปลี่ยนสถาปัตยกรรมและสร้าง "smart backend" สำหรับการโหลดข้อมูลแบบค่อยเป็นค่อยไปผ่าน WebSockets

    • มีความกังวลเกี่ยวกับปัญหาด้านความปลอดภัยของข้อมูล gob
  • มีความเห็นว่า WASM เหมาะกับงานเฉพาะทางบางอย่าง แต่ไม่เหมาะกับการสร้างเว็บแอปทั่วไป

    • แอปที่สร้างด้วย go-app โหลดโค้ด WASM ขนาด 3.6MB
    • Blazor ก็เช่นกัน ต่อให้เป็นแอปง่าย ๆ ก็ยังต้องใช้การโหลดเริ่มต้นอย่างน้อย 1MB
  • มีความเห็นว่าการใช้ภาษาเดียวกันกับทุกองค์ประกอบ (ฟรอนต์เอนด์/แบ็กเอนด์/แอป) มีคุณค่ามาก

    • ในทางกลับกัน บางคนใช้แนวทาง "Typescript everywhere" โดยใช้ React สำหรับฟรอนต์เอนด์, NodeJS สำหรับแบ็กเอนด์ และ Capacitor สำหรับแอป