Vapor Mode ของ Vue 3.6 ที่กำลังจะมาถึงจะเปิดตัวในฤดูใบไม้ร่วงนี้ และมันทำในสิ่งที่เฟรมเวิร์กไม่เคยทำมาก่อน นั่นคือการคอมไพล์ single-file components ให้เป็นการอัปเดตไปยัง DOM โดยตรง โดยข้ามขั้นตอนของ virtual DOM ไปอย่างสิ้นเชิง

ทำไม Vue ถึงหันหลังให้ virtual DOM

ตั้งแต่ Vue 2 เป็นต้นมา virtual DOM ได้เป็นหัวใจสำคัญของโมเดล reactivity ของเฟรมเวิร์ก เมื่อสถานะ (state) เปลี่ยนแปลง Vue จะสร้าง tree ขนาดเล็กในหน่วยความจำ เปรียบเทียบความแตกต่าง (diff) กับเวอร์ชันก่อนหน้า และอัปเดต (patch) เฉพาะส่วนที่แตกต่างกันเท่านั้น การทำงานผ่านตัวกลางนี้ช่วยให้นักพัฒนาเขียนโค้ดแบบ declarative ได้โดยไม่ต้องกังวลว่าองค์ประกอบใดที่จำเป็นต้องอัปเดตจริง ๆ แต่ข้อแลกเปลี่ยนคือ ทุกการเรนเดอร์ยังคงต้องเสียต้นทุนในการสร้างและเปรียบเทียบ virtual tree นั้น

Vapor Mode ตัดขั้นตอนกลางนั้นออกไป ในระหว่างการ build ตัวคอมไพเลอร์ของ Vue จะวิเคราะห์เทมเพลตและสร้าง JavaScript ที่เรียกใช้เมธอด DOM พื้นฐาน—element.textContent = …, element.setAttribute(...)—โดยตรงในจุดที่จำเป็นต้องมีการเปลี่ยนแปลง จะไม่มีการสร้าง virtual nodes และไม่มีการรันลูปการ diff ผลลัพธ์ที่ได้คือ bundle จะประกอบด้วยเฉพาะโค้ดที่จำเป็นสำหรับการอัปเดตที่จับต้องได้ที่คุณเขียนขึ้น บวกกับ runtime ที่จำเป็นสำหรับ reactivity เท่านั้น

ผลกระทบในโลกความเป็นจริงต่อขนาดและความเร็ว

  • ขนาดของ bundle – ด้วยการตัด runtime ของ virtual-DOM และโครงสร้างข้อมูลออกไป โค้ดที่ถูกสร้างขึ้นจึงมีขนาดเล็กลง ในโปรเจกต์ที่มี grid หรือ canvas ขนาดใหญ่ซึ่งมีการอัปเดตหลายสิบครั้งต่อวินาที การประหยัดพื้นที่เหล่านี้จะสะสมมากขึ้นเรื่อย ๆ โดยเฉพาะในการเชื่อมต่อที่มีแบนด์วิดท์ต่ำ
  • ประสิทธิภาพ – การเรียก DOM โดยตรงจะข้ามขั้นตอนการทำงานส่วนเกินของการ diff ซึ่งจะเห็นผลได้ชัดเจนเมื่อ UI มีการเปลี่ยนแปลงด้วยความถี่สูง ในชุดเกมบนเบราว์เซอร์ส่วนตัวของผม—ซึ่งประกอบด้วย nonogram, เกมเลียนแบบ minesweeper และโปรแกรมแสดงภาพ Rubik’s-cube แบบ 3 มิติ—ผมเขียนตรรกะการเรนเดอร์ด้วยตัวเอง โดยอัปเดต DOM เฉพาะจุดที่จำเป็นเท่านั้น
  • ความสะดวกในการใช้งานสำหรับนักพัฒนา (Developer ergonomics) – คอมไพเลอร์จะเป็นผู้จัดการงานหนักให้ คุณยังคงเขียน Vue templates ตามปกติ โดยไม่ต้องเขียนคำสั่ง document.querySelector ด้วยตัวเอง โค้ดที่ถูกสร้างขึ้นจะสะท้อนถึงวิธีการเขียนด้วยมือที่ให้ประสิทธิภาพดีที่สุดในเกมเหล่านั้นของผม

เมื่อไหร่ที่ Vapor Mode จะช่วยได้จริง ๆ

  1. การอัปเดตความถี่สูงบนโครงสร้างขนาดใหญ่ – เกม, แดชบอร์ดที่ใช้ข้อมูลเข้มข้น หรืออินเทอร์เฟซใด ๆ ที่ต้องวาดเซลล์จำนวนมากในแต่ละรอบ (tick) จะได้รับประโยชน์สูงสุด การ diff grid ขนาดใหญ่ในทุก ๆ tick อาจกินงบประมาณเฟรม (frame budget) ไปมาก การอัปเดตโดยตรงจะช่วยให้การทำงานเป็นแบบเชิงเส้น (linear) และคาดเดาได้
  2. การปรับใช้ที่มีข้อจำกัดด้านขนาด bundle – เว็บไซต์ที่เน้นการใช้งานบนมือถือ (mobile-first) ซึ่งต้องโหลดให้เสร็จภายในไม่กี่ร้อยกิโลไบต์ จะเห็นการลดลงของขนาดอย่างชัดเจนเมื่อ runtime ของ virtual-DOM หายไป
  3. สถานะ (state) ที่บริสุทธิ์และคาดเดาได้ – Vapor Mode ตั้งสมมติฐานว่าคุณเก็บ state แบบ immutable และปฏิบัติกับ DOM ในฐานะการแสดงผล (projection) ที่บริสุทธิ์ของ state นั้น หากโค้ดของคุณมีการผสมผสาน side-effects หรือแก้ไข DOM นอกระบบ reactivity ของ Vue การอัปเดตที่ถูกสร้างขึ้นอาจไม่ตรงกัน (out of sync) และทำให้เกิดความผิดพลาดทางภาพ (visual glitches)

เมื่อไหร่ที่แนวทางแบบเดิมยังคงชนะ

  • UI ที่มีการอัปเดตความถี่ต่ำ – ฟอร์มง่าย ๆ, หน้าเว็บแบบสแตติก หรือแผงควบคุม (admin panels) ที่จะเรนเดอร์ใหม่เฉพาะเมื่อมีการกระทำของผู้ใช้เป็นครั้งคราว จะได้รับประสิทธิภาพเพิ่มขึ้นเพียงเล็กน้อย งานส่วนเกินในการสร้าง virtual tree นั้นถือว่าน้อยมากเมื่อเทียบกับความหน่วงของเครือข่าย (network latency) หรือเวลาในการประมวลผลของเซิร์ฟเวอร์
  • ลำดับชั้นของคอมโพเนนต์ที่ซับซ้อน – เมื่อ tree ที่มีความลึกมีการเปลี่ยนแปลงเพียงแค่ leaf node ตัว virtual DOM สามารถข้ามส่วนใหญ่ไปได้โดยอัตโนมัติ แต่การอัปเดตโดยตรงจะบังคับให้คอมไพเลอร์ต้องสร้าง patch ที่แม่นยำสำหรับการเปลี่ยนแปลงที่เป็นไปได้แต่ละอย่าง ซึ่งอาจเพิ่มขนาดโค้ดในกรณีพิเศษ (edge cases)
  • เครื่องมือและระบบนิเวศ (Ecosystem) – ปลั๊กอิน Vue, devtools และเครื่องมือทดสอบจำนวนมากเชื่อมต่อเข้ากับเลเยอร์ของ virtual-DOM การรวมระบบเหล่านี้อาจจำเป็นต้องได้รับการอัปเดตเพื่อให้ทำงานร่วมกับคอมโพเนนต์ใน Vapor-mode ได้ จนกว่าระบบนิเวศจะตามทัน

สิ่งที่ต้องจับตามองต่อไป

  • เวอร์ชันเสถียร (Stable release) – Vue 3.6 อยู่ในสถานะ release-candidate ทีมงานวางแผนที่จะเปิดตัวเวอร์ชันเสถียรในช่วงฤดูใบไม้ร่วงนี้ ผู้ที่ต้องการเริ่มใช้งานเร็ว (early adopters) ควรควรรอเวอร์ชันนั้นก่อนที่จะนำไปใช้กับโค้ดในระดับโปรดักชัน
  • แนวทางการย้ายระบบ (Migration path) – โปรเจกต์ Vue ที่มีอยู่สามารถเลือกใช้ Vapor Mode ได้เป็นรายคอมโพเนนต์
  • เครื่องมือวัดประสิทธิภาพ – การทดสอบประสิทธิภาพ (benchmarks) ที่เปรียบเทียบระหว่างการสร้างแบบ virtual-DOM และ Vapor-mode ในแอปพลิเคชันที่ใช้งานจริง จะช่วยให้ทีมตัดสินใจได้ว่าความคุ้มค่าในการแลกเปลี่ยนนั้นมีมากน้อยเพียงใด

สรุปสาระสำคัญ

Vapor Mode มอบสิ่งที่ดีที่สุดจากทั้งสองโลกให้กับนักพัฒนา Vue นั่นคือไวยากรณ์แบบ declarative ที่พวกเขาชื่นชอบ และความเร็วที่แท้จริงของการอัปเดต DOM ที่เขียนขึ้นเอง มันโดดเด่นสำหรับแอปพลิเคชันที่ต้องรีเฟรชส่วนต่าง ๆ ของ UI จำนวนมากหลายครั้งต่อวินาที และสำหรับการปรับใช้งานที่ทุก ๆ กิโลไบต์มีความสำคัญ สำหรับอินเทอร์เฟซที่มีการใช้งานน้อย virtual DOM แบบดั้งเดิมยังคงเป็นทางเลือกที่เรียบง่ายและใช้งานได้ดีเยี่ยม เมื่อฟีเจอร์นี้เปลี่ยนจากเวอร์ชัน release candidate ไปสู่เวอร์ชัน stable ชุมชน Vue จะต้องชั่งน้ำหนักระหว่างการประหยัดขนาด bundle กับความพร้อมของ ecosystem และรูปแบบประสิทธิภาพเฉพาะตัวของแอปพลิเคชันของตนเอง