เจาะลึกสถาปัตยกรรม Fiber ของ React อธิบายกระบวนการ Reconciliation ประโยชน์ และวิธีปรับปรุงประสิทธิภาพแอปพลิเคชัน
สถาปัตยกรรม React Fiber: ทำความเข้าใจกระบวนการ Reconciliation
React ได้ปฏิวัติการพัฒนา Front-end ด้วยสถาปัตยกรรมแบบคอมโพเนนต์และโมเดลการเขียนโปรแกรมเชิงประกาศ หัวใจสำคัญของประสิทธิภาพของ React คือกระบวนการ Reconciliation ซึ่งเป็นกลไกที่ React ใช้ในการอัปเดต DOM จริงเพื่อให้สะท้อนถึงการเปลี่ยนแปลงในโครงสร้างคอมโพเนนต์ กระบวนการนี้ได้มีการพัฒนาอย่างต่อเนื่อง จนมาถึงสถาปัตยกรรม Fiber บทความนี้จะให้ความเข้าใจที่ครอบคลุมเกี่ยวกับ React Fiber และผลกระทบต่อ Reconciliation
Reconciliation คืออะไร?
Reconciliation คืออัลกอริทึมที่ React ใช้ในการเปรียบเทียบ virtual DOM เดิมกับ virtual DOM ใหม่ และกำหนดชุดการเปลี่ยนแปลงที่น้อยที่สุดที่จำเป็นในการอัปเดต DOM จริง Virtual DOM คือการแสดงผล UI ในหน่วยความจำ เมื่อสถานะของคอมโพเนนต์เปลี่ยนแปลง React จะสร้าง virtual DOM ใหม่ แทนที่จะจัดการ DOM จริงโดยตรงซึ่งเป็นกระบวนการที่ช้า React จะเปรียบเทียบ virtual DOM ใหม่กับอันก่อนหน้าและระบุความแตกต่าง กระบวนการนี้เรียกว่า diffing
กระบวนการ Reconciliation ดำเนินการโดยมีสมมติฐานหลักสองประการ:
- องค์ประกอบที่มีประเภทต่างกันจะสร้างโครงสร้างที่แตกต่างกัน
- นักพัฒนาสามารถบ่งชี้ว่าองค์ประกอบย่อยใดอาจมีความเสถียรข้ามการ Render ที่แตกต่างกัน โดยใช้ prop
key
Reconciliation แบบดั้งเดิม (ก่อน Fiber)
ในการใช้งาน React เริ่มต้น กระบวนการ Reconciliation เป็นแบบซิงโครนัสและไม่สามารถแบ่งแยกได้ ซึ่งหมายความว่าเมื่อ React เริ่มกระบวนการเปรียบเทียบ virtual DOM และอัปเดต DOM จริง จะไม่สามารถขัดจังหวะได้ สิ่งนี้อาจนำไปสู่ปัญหาด้านประสิทธิภาพ โดยเฉพาะอย่างยิ่งในแอปพลิเคชันที่ซับซ้อนซึ่งมีโครงสร้างคอมโพเนนต์ขนาดใหญ่ หากการอัปเดตคอมโพเนนต์ใช้เวลานาน เบราว์เซอร์จะตอบสนองไม่ได้ ส่งผลให้ประสบการณ์ผู้ใช้ไม่ดี สิ่งนี้มักเรียกว่าปัญหา "jank"
ลองนึกภาพเว็บไซต์อีคอมเมิร์ซที่ซับซ้อนซึ่งแสดงรายการสินค้า หากผู้ใช้โต้ตอบกับตัวกรอง ทำให้เกิดการ Render รายการใหม่ กระบวนการ Reconciliation แบบซิงโครนัสอาจบล็อกเธรดหลัก ทำให้ UI ไม่ตอบสนองจนกว่ารายการทั้งหมดจะถูก Render ใหม่ ซึ่งอาจใช้เวลาหลายวินาที ทำให้ผู้ใช้หงุดหงิด
แนะนำ React Fiber
React Fiber คือการเขียนอัลกอริทึม Reconciliation ของ React ใหม่ทั้งหมด ซึ่งเปิดตัวใน React 16 เป้าหมายหลักคือการปรับปรุงการตอบสนองและประสิทธิภาพที่รับรู้ของแอปพลิเคชัน React โดยเฉพาะในสถานการณ์ที่ซับซ้อน Fiber บรรลุเป้าหมายนี้โดยการแบ่งกระบวนการ Reconciliation ออกเป็นหน่วยการทำงานที่เล็กและสามารถขัดจังหวะได้
แนวคิดหลักเบื้องหลัง React Fiber คือ:
- Fibers: Fiber คือออบเจกต์ JavaScript ที่แสดงถึงหน่วยการทำงาน มันเก็บข้อมูลเกี่ยวกับคอมโพเนนต์ อินพุต และเอาต์พุตของคอมโพเนนต์ คอมโพเนนต์ React แต่ละตัวมี Fiber ที่สอดคล้องกัน
- WorkLoop: Work loop คือลูปที่วนซ้ำผ่านโครงสร้าง Fiber และทำงานที่จำเป็นสำหรับแต่ละ Fiber
- Scheduling: Scheduler จะตัดสินใจว่าจะเริ่ม หยุด ดำเนินการต่อ หรือยกเลิกหน่วยการทำงานตามลำดับความสำคัญ
ประโยชน์ของสถาปัตยกรรม Fiber
สถาปัตยกรรม Fiber มีประโยชน์ที่สำคัญหลายประการ:
- Reconciliation ที่ขัดจังหวะได้: Fiber ช่วยให้ React สามารถหยุดและดำเนินการต่อกระบวนการ Reconciliation ป้องกันไม่ให้งานที่ใช้เวลานานบล็อกเธรดหลัก สิ่งนี้ทำให้มั่นใจได้ว่า UI จะยังคงตอบสนองได้ แม้ในช่วงที่มีการอัปเดตที่ซับซ้อน
- การอัปเดตตามลำดับความสำคัญ: Fiber ช่วยให้ React สามารถจัดลำดับความสำคัญของการอัปเดตที่แตกต่างกันได้ ตัวอย่างเช่น การโต้ตอบของผู้ใช้ เช่น การพิมพ์หรือการคลิก สามารถให้ลำดับความสำคัญสูงกว่างานเบื้องหลัง เช่น การดึงข้อมูล สิ่งนี้ทำให้มั่นใจได้ว่าการอัปเดตที่สำคัญที่สุดจะได้รับการประมวลผลก่อน
- การแสดงผลแบบอะซิงโครนัส: Fiber ช่วยให้ React สามารถดำเนินการแสดงผลแบบอะซิงโครนัสได้ ซึ่งหมายความว่า React สามารถเริ่มแสดงผลคอมโพเนนต์และหยุดชั่วคราวเพื่อให้เบราว์เซอร์จัดการกับงานอื่น ๆ ได้ เช่น การป้อนข้อมูลของผู้ใช้หรือแอนิเมชัน สิ่งนี้ช่วยปรับปรุงประสิทธิภาพโดยรวมและการตอบสนองของแอปพลิเคชัน
- การจัดการข้อผิดพลาดที่ดีขึ้น: Fiber ให้การจัดการข้อผิดพลาดที่ดีขึ้นในระหว่างกระบวนการ Reconciliation หากเกิดข้อผิดพลาดระหว่างการแสดงผล React สามารถกู้คืนได้ดีขึ้นและป้องกันไม่ให้แอปพลิเคชันทั้งหมดล่ม
พิจารณาแอปพลิเคชันแก้ไขเอกสารร่วมกัน ด้วย Fiber การแก้ไขที่ทำโดยผู้ใช้ที่แตกต่างกันสามารถประมวลผลตามลำดับความสำคัญที่แตกต่างกัน การพิมพ์แบบเรียลไทม์จากผู้ใช้ปัจจุบันจะได้รับลำดับความสำคัญสูงสุด เพื่อให้แน่ใจว่ามีการตอบสนองทันที การอัปเดตจากผู้ใช้อื่น หรือการบันทึกอัตโนมัติเบื้องหลัง สามารถประมวลผลด้วยลำดับความสำคัญที่ต่ำกว่า โดยลดการรบกวนประสบการณ์ของผู้ใช้ที่ใช้งานอยู่
ทำความเข้าใจโครงสร้าง Fiber
คอมโพเนนต์ React แต่ละตัวจะแสดงด้วยโหนด Fiber โหนด Fiber จะเก็บข้อมูลเกี่ยวกับประเภทของคอมโพเนนต์ props สถานะ และความสัมพันธ์กับโหนด Fiber อื่น ๆ ในโครงสร้าง นี่คือคุณสมบัติที่สำคัญบางประการของโหนด Fiber:
- type: ประเภทของคอมโพเนนต์ (เช่น คอมโพเนนต์ฟังก์ชัน คอมโพเนนต์คลาส องค์ประกอบ DOM)
- key: prop key ที่ส่งไปยังคอมโพเนนต์
- props: props ที่ส่งไปยังคอมโพเนนต์
- stateNode: อินสแตนซ์ของคอมโพเนนต์ (สำหรับคอมโพเนนต์คลาส) หรือ null (สำหรับคอมโพเนนต์ฟังก์ชัน)
- child: ตัวชี้ไปยังโหนด Fiber ลูกตัวแรก
- sibling: ตัวชี้ไปยังโหนด Fiber พี่น้องตัวถัดไป
- return: ตัวชี้ไปยังโหนด Fiber ของพ่อ
- alternate: ตัวชี้ไปยังโหนด Fiber ที่แสดงสถานะก่อนหน้าของคอมโพเนนต์
- effectTag: ธงที่บ่งชี้ประเภทของการอัปเดตที่ต้องดำเนินการบน DOM
คุณสมบัติ alternate
มีความสำคัญเป็นพิเศษ ช่วยให้ React ติดตามสถานะก่อนหน้าและสถานะปัจจุบันของคอมโพเนนต์ ในระหว่างกระบวนการ Reconciliation React จะเปรียบเทียบโหนด Fiber ปัจจุบันกับ alternate
เพื่อกำหนดการเปลี่ยนแปลงที่ต้องทำกับ DOM
อัลกอริทึม WorkLoop
Work loop คือแกนหลักของสถาปัตยกรรม Fiber มีหน้าที่ในการวนซ้ำโครงสร้าง Fiber และดำเนินการที่จำเป็นสำหรับแต่ละ Fiber Work loop ถูกนำไปใช้เป็นฟังก์ชันเรียกซ้ำที่ประมวลผล Fiber ทีละรายการ
Work loop ประกอบด้วยสองเฟสหลัก:
- Render Phase: ในระหว่าง Render Phase React จะวนซ้ำโครงสร้าง Fiber และกำหนดการเปลี่ยนแปลงที่ต้องทำกับ DOM เฟสนี้สามารถขัดจังหวะได้ หมายความว่า React สามารถหยุดและดำเนินการต่อได้ตลอดเวลา
- Commit Phase: ในระหว่าง Commit Phase React จะนำการเปลี่ยนแปลงไปใช้กับ DOM เฟสนี้ไม่สามารถขัดจังหวะได้ หมายความว่า React ต้องทำให้เสร็จสมบูรณ์เมื่อเริ่มทำงาน
Render Phase โดยละเอียด
Render Phase สามารถแบ่งออกเป็นสองเฟสย่อยได้:
- beginWork: ฟังก์ชัน
beginWork
มีหน้าที่ประมวลผลโหนด Fiber ปัจจุบันและสร้างโหนด Fiber ลูก มันจะกำหนดว่าคอมโพเนนต์จำเป็นต้องอัปเดตหรือไม่ และหากเป็นเช่นนั้น จะสร้างโหนด Fiber ใหม่สำหรับรายการย่อย - completeWork: ฟังก์ชัน
completeWork
มีหน้าที่ประมวลผลโหนด Fiber ปัจจุบันหลังจากที่รายการย่อยได้รับการประมวลผลแล้ว มันจะอัปเดต DOM และคำนวณเค้าโครงของคอมโพเนนต์
ฟังก์ชัน beginWork
ทำงานดังนี้:
- ตรวจสอบว่าคอมโพเนนต์จำเป็นต้องอัปเดตหรือไม่
- หากคอมโพเนนต์จำเป็นต้องอัปเดต จะเปรียบเทียบ props และ state ใหม่กับ props และ state ก่อนหน้าเพื่อกำหนดการเปลี่ยนแปลงที่ต้องทำ
- สร้างโหนด Fiber ใหม่สำหรับรายการย่อยของคอมโพเนนต์
- ตั้งค่าคุณสมบัติ
effectTag
บนโหนด Fiber เพื่อบ่งชี้ประเภทของการอัปเดตที่ต้องดำเนินการบน DOM
ฟังก์ชัน completeWork
ทำงานดังนี้:
- อัปเดต DOM ด้วยการเปลี่ยนแปลงที่กำหนดไว้ในระหว่างฟังก์ชัน
beginWork
- คำนวณเค้าโครงของคอมโพเนนต์
- รวบรวมผลข้างเคียงที่ต้องดำเนินการหลัง Commit Phase
Commit Phase โดยละเอียด
Commit Phase มีหน้าที่นำการเปลี่ยนแปลงไปใช้กับ DOM เฟสนี้ไม่สามารถขัดจังหวะได้ หมายความว่า React ต้องทำให้เสร็จสมบูรณ์เมื่อเริ่มทำงาน Commit Phase ประกอบด้วยสามเฟสย่อย:
- beforeMutation: เฟสนี้จะดำเนินการก่อนที่ DOM จะถูกเปลี่ยนแปลง ใช้สำหรับดำเนินการต่างๆ เช่น การเตรียม DOM สำหรับการอัปเดต
- mutation: เฟสนี้คือที่ที่การเปลี่ยนแปลง DOM จริงเกิดขึ้น React จะอัปเดต DOM ตามคุณสมบัติ
effectTag
ของโหนด Fiber - layout: เฟสนี้จะดำเนินการหลังจากการเปลี่ยนแปลง DOM ถูกทำขึ้น ใช้สำหรับดำเนินการต่างๆ เช่น การอัปเดตเค้าโครงของคอมโพเนนต์และการเรียกใช้เมธอด Lifecycle
ตัวอย่างและการใช้งานจริง
ให้เราแสดงกระบวนการ Reconciliation ของ Fiber ด้วยตัวอย่างที่ง่ายขึ้น พิจารณาคอมโพเนนต์ที่แสดงรายการ:
```javascript function ItemList({ items }) { return (-
{items.map(item => (
- {item.name} ))}
เมื่อ prop items
เปลี่ยน React จะต้องทำการ Reconciliation รายการและอัปเดต DOM ตามลำดับ นี่คือวิธีที่ Fiber จะจัดการกับสิ่งนี้:
- Render Phase: ฟังก์ชัน
beginWork
จะเปรียบเทียบอาร์เรย์items
ใหม่กับอาร์เรย์items
ก่อนหน้า มันจะระบุว่ารายการใดถูกเพิ่ม ลบ หรืออัปเดต - จะมีการสร้างโหนด Fiber ใหม่สำหรับรายการที่เพิ่มเข้ามา และ
effectTag
จะถูกตั้งค่าเพื่อบ่งชี้ว่ารายการเหล่านี้ต้องถูกแทรกเข้าไปใน DOM - โหนด Fiber สำหรับรายการที่ถูกลบจะถูกทำเครื่องหมายเพื่อลบ
- โหนด Fiber สำหรับรายการที่อัปเดตจะถูกอัปเดตด้วยข้อมูลใหม่
- Commit Phase: Commit Phase จะนำการเปลี่ยนแปลงเหล่านี้ไปใช้กับ DOM จริง รายการที่เพิ่มเข้ามาจะถูกแทรก รายการที่ถูกลบจะถูกลบ และรายการที่อัปเดตจะถูกแก้ไข
การใช้ prop key
มีความสำคัญอย่างยิ่งสำหรับ Reconciliation ที่มีประสิทธิภาพ หากไม่มี prop key
React จะต้อง Render รายการทั้งหมดใหม่ทุกครั้งที่อาร์เรย์ items
เปลี่ยนแปลง ด้วย prop key
React สามารถระบุได้อย่างรวดเร็วว่ารายการใดถูกเพิ่ม ลบ หรืออัปเดต และอัปเดตเฉพาะรายการเหล่านั้น
ตัวอย่างเช่น ลองนึกภาพสถานการณ์ที่ลำดับของรายการในตะกร้าสินค้าเปลี่ยนแปลง หากแต่ละรายการมี key
ที่ไม่ซ้ำกัน (เช่น ID สินค้า) React สามารถจัดลำดับรายการใน DOM ใหม่ได้อย่างมีประสิทธิภาพโดยไม่ต้อง Render ใหม่ทั้งหมด สิ่งนี้ช่วยเพิ่มประสิทธิภาพอย่างมาก โดยเฉพาะอย่างยิ่งสำหรับรายการขนาดใหญ่
การ Scheduling และการจัดลำดับความสำคัญ
หนึ่งในประโยชน์หลักของ Fiber คือความสามารถในการ Schedule และจัดลำดับความสำคัญของการอัปเดต React ใช้ Scheduler เพื่อตัดสินใจว่าจะเริ่ม หยุด ดำเนินการต่อ หรือยกเลิกหน่วยการทำงานตามลำดับความสำคัญ สิ่งนี้ช่วยให้ React สามารถจัดลำดับความสำคัญของการโต้ตอบของผู้ใช้และทำให้มั่นใจได้ว่า UI จะยังคงตอบสนองได้ แม้ในช่วงที่มีการอัปเดตที่ซับซ้อน
React มี API หลายอย่างสำหรับการ Schedule การอัปเดตด้วยลำดับความสำคัญที่แตกต่างกัน:
React.render
: Schedule การอัปเดตด้วยลำดับความสำคัญเริ่มต้นReactDOM.unstable_deferredUpdates
: Schedule การอัปเดตด้วยลำดับความสำคัญที่ต่ำกว่าReactDOM.unstable_runWithPriority
: อนุญาตให้คุณระบุลำดับความสำคัญของการอัปเดตได้อย่างชัดเจน
ตัวอย่างเช่น คุณสามารถใช้ ReactDOM.unstable_deferredUpdates
เพื่อ Schedule การอัปเดตที่ไม่สำคัญต่อประสบการณ์ของผู้ใช้ เช่น การติดตาม Analytics หรือการดึงข้อมูลเบื้องหลัง
การจัดการข้อผิดพลาดด้วย Fiber
Fiber ให้การจัดการข้อผิดพลาดที่ดีขึ้นในระหว่างกระบวนการ Reconciliation เมื่อเกิดข้อผิดพลาดระหว่างการแสดงผล React สามารถจับข้อผิดพลาดและป้องกันไม่ให้แอปพลิเคชันทั้งหมดล่ม React ใช้ Error Boundaries เพื่อจัดการข้อผิดพลาดในลักษณะที่ควบคุมได้
Error boundary คือคอมโพเนนต์ที่จับข้อผิดพลาด JavaScript ที่ใดก็ได้ในโครงสร้างคอมโพเนนต์ย่อย บันทึกข้อผิดพลาดเหล่านั้น และแสดง UI สำรองแทนโครงสร้างคอมโพเนนต์ที่ล้มเหลว Error boundaries จับข้อผิดพลาดระหว่างการแสดงผล ในเมธอด Lifecycle และใน Constructor ของโครงสร้างทั้งหมดด้านล่าง
```javascript class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error, errorInfo) { // You can also log the error to an error reporting service logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // You can render any custom fallback UI returnSomething went wrong.
; } return this.props.children; } } ```คุณสามารถใช้ Error boundaries เพื่อครอบคลุมคอมโพเนนต์ใดๆ ที่อาจเกิดข้อผิดพลาด สิ่งนี้จะช่วยให้มั่นใจได้ว่าแอปพลิเคชันของคุณยังคงเสถียรแม้ว่าบางคอมโพเนนต์จะล้มเหลว
```javascriptการดีบัก Fiber
การดีบักแอปพลิเคชัน React ที่ใช้ Fiber อาจเป็นเรื่องท้าทาย แต่ก็มีเครื่องมือและเทคนิคหลายอย่างที่สามารถช่วยได้ ส่วนขยายเบราว์เซอร์ React DevTools ให้ชุดเครื่องมือที่ทรงพลังสำหรับการตรวจสอบโครงสร้างคอมโพเนนต์ การ Profiling ประสิทธิภาพ และการดีบักข้อผิดพลาด
React Profiler ช่วยให้คุณบันทึกประสิทธิภาพของแอปพลิเคชันของคุณและระบุคอขวด คุณสามารถใช้ Profiler เพื่อดูว่าแต่ละคอมโพเนนต์ใช้เวลานานเท่าใดในการ Render และระบุคอมโพเนนต์ที่ก่อให้เกิดปัญหาด้านประสิทธิภาพ
React DevTools ยังมีมุมมองโครงสร้างคอมโพเนนต์ที่ช่วยให้คุณตรวจสอบ props สถานะ และโหนด Fiber ของแต่ละคอมโพเนนต์ สิ่งนี้จะเป็นประโยชน์ในการทำความเข้าใจว่าโครงสร้างคอมโพเนนต์ถูกจัดโครงสร้างอย่างไร และกระบวนการ Reconciliation ทำงานอย่างไร
สรุป
สถาปัตยกรรม React Fiber แสดงถึงการปรับปรุงที่สำคัญเหนือกระบวนการ Reconciliation แบบดั้งเดิม ด้วยการแบ่งกระบวนการ Reconciliation ออกเป็นหน่วยการทำงานที่เล็กและสามารถขัดจังหวะได้ Fiber ช่วยให้ React สามารถปรับปรุงการตอบสนองและประสิทธิภาพที่รับรู้ของแอปพลิเคชัน โดยเฉพาะในสถานการณ์ที่ซับซ้อน
การทำความเข้าใจแนวคิดหลักเบื้องหลัง Fiber เช่น Fibers, Work Loops และ Scheduling เป็นสิ่งจำเป็นสำหรับการสร้างแอปพลิเคชัน React ที่มีประสิทธิภาพสูง ด้วยการใช้ประโยชน์จากคุณสมบัติของ Fiber คุณสามารถสร้าง UI ที่ตอบสนองได้ดีขึ้น ทนทานมากขึ้น และมอบประสบการณ์ผู้ใช้ที่ดีขึ้น
ในขณะที่ React ยังคงพัฒนาต่อไป Fiber จะยังคงเป็นส่วนสำคัญของสถาปัตยกรรม การติดตามการพัฒนาล่าสุดของ Fiber จะช่วยให้คุณมั่นใจได้ว่าแอปพลิเคชัน React ของคุณจะได้รับประโยชน์ด้านประสิทธิภาพอย่างเต็มที่
นี่คือประเด็นสำคัญ:
- React Fiber คือการเขียนอัลกอริทึม Reconciliation ของ React ใหม่ทั้งหมด
- Fiber ช่วยให้ React สามารถหยุดและดำเนินการต่อกระบวนการ Reconciliation ป้องกันไม่ให้งานที่ใช้เวลานานบล็อกเธรดหลัก
- Fiber ช่วยให้ React สามารถจัดลำดับความสำคัญของการอัปเดตที่แตกต่างกัน
- Fiber ให้การจัดการข้อผิดพลาดที่ดีขึ้นในระหว่างกระบวนการ Reconciliation
- Prop
key
มีความสำคัญอย่างยิ่งต่อ Reconciliation ที่มีประสิทธิภาพ - ส่วนขยายเบราว์เซอร์ React DevTools ให้ชุดเครื่องมือที่ทรงพลังสำหรับการดีบักแอปพลิเคชัน Fiber
ด้วยการยอมรับ React Fiber และทำความเข้าใจหลักการของมัน นักพัฒนาทั่วโลกสามารถสร้างเว็บแอปพลิเคชันที่มีประสิทธิภาพและใช้งานง่ายยิ่งขึ้น โดยไม่คำนึงถึงสถานที่หรือความซับซ้อนของโครงการของพวกเขา