เชี่ยวชาญการเพิ่มประสิทธิภาพประสิทธิภาพของ React ด้วย Fiber Concurrent Mode Profiler แสดงภาพคอขวดของการเรนเดอร์ ระบุปัญหาด้านประสิทธิภาพ และสร้างแอปพลิเคชันที่รวดเร็วและตอบสนองได้ดีขึ้น
React Fiber Concurrent Mode Profiler: การแสดงภาพประสิทธิภาพการเรนเดอร์
React Fiber ซึ่งเปิดตัวใน React 16 ได้ปฏิวัติวิธีการที่ React จัดการการอัปเดต DOM Concurrent Mode ซึ่งสร้างขึ้นบน Fiber จะปลดล็อกความสามารถอันทรงพลังสำหรับการสร้างอินเทอร์เฟซผู้ใช้ที่ตอบสนองได้ดี อย่างไรก็ตาม การทำความเข้าใจและการเพิ่มประสิทธิภาพใน Concurrent Mode จำเป็นต้องมีเครื่องมือพิเศษ นี่คือที่มาของ React Fiber Concurrent Mode Profiler
React Fiber คืออะไร
ก่อนที่จะเจาะลึก Profiler เรามาทบทวน React Fiber สั้นๆ กันก่อน ตามเนื้อผ้า React ใช้กระบวนการกระทบยอดแบบซิงโครนัส เมื่อสถานะของคอมโพเนนต์เปลี่ยนแปลง React จะเรนเดอร์แผนผังคอมโพเนนต์ทั้งหมดใหม่ทันที ซึ่งอาจบล็อกเธรดหลักและนำไปสู่ UI ที่กระตุก โดยเฉพาะอย่างยิ่งสำหรับแอปพลิเคชันที่ซับซ้อน Fiber แก้ไขข้อจำกัดนี้โดยการแนะนำอัลกอริทึมการกระทบยอดแบบอะซิงโครนัสที่สามารถขัดจังหวะได้
ประโยชน์หลักของ Fiber ได้แก่:
- การจัดลำดับความสำคัญ: Fiber อนุญาตให้ React จัดลำดับความสำคัญของการอัปเดตตามความสำคัญ การอัปเดตที่สำคัญ (เช่น อินพุตของผู้ใช้) สามารถประมวลผลได้ทันที ในขณะที่การอัปเดตที่เร่งด่วนน้อยกว่า (เช่น การดึงข้อมูลพื้นหลัง) สามารถเลื่อนออกไปได้
- ความสามารถในการขัดจังหวะ: React สามารถหยุดชั่วคราว ทำต่อ หรือละทิ้งงานการเรนเดอร์ได้ตามต้องการ ป้องกันไม่ให้งานที่ใช้เวลานานบล็อก UI
- การเรนเดอร์แบบเพิ่มหน่วย: Fiber แบ่งการเรนเดอร์ออกเป็นหน่วยงานที่เล็กลง ทำให้ React สามารถอัปเดต DOM ในหน่วยที่เล็กลง ปรับปรุงประสิทธิภาพที่รับรู้ได้
ทำความเข้าใจ Concurrent Mode
Concurrent Mode สร้างขึ้นบน Fiber เพื่อปลดล็อกคุณสมบัติขั้นสูงสำหรับการสร้างแอปพลิเคชันที่ตอบสนองและโต้ตอบได้มากขึ้น โดยจะแนะนำ API ใหม่และกลยุทธ์การเรนเดอร์ที่อนุญาตให้ React ทำสิ่งต่อไปนี้:
- Transition API: อนุญาตให้คุณทำเครื่องหมายการอัปเดตเป็นการเปลี่ยนภาพ โดยระบุว่าอาจใช้เวลานานกว่าในการเรนเดอร์โดยไม่บล็อก UI ซึ่งช่วยให้ React จัดลำดับความสำคัญของการโต้ตอบของผู้ใช้ในขณะที่ค่อยๆ อัปเดตส่วนที่ไม่สำคัญของหน้าจอ
- Suspense: ช่วยให้คุณจัดการสถานะการโหลดอย่างสวยงามสำหรับการดึงข้อมูลและการแยกโค้ด คุณสามารถแสดง UI สำรอง (เช่น ตัวหมุน ตัวยึดตำแหน่ง) ในขณะที่กำลังโหลดข้อมูล ซึ่งจะช่วยปรับปรุงประสบการณ์ของผู้ใช้
- Offscreen Rendering: อนุญาตให้คุณเรนเดอร์คอมโพเนนต์ในพื้นหลัง เพื่อให้พร้อมที่จะแสดงทันทีเมื่อจำเป็น
ขอแนะนำ React Fiber Concurrent Mode Profiler
React Fiber Concurrent Mode Profiler เป็นเครื่องมือที่ทรงพลังสำหรับการแสดงภาพและวิเคราะห์ประสิทธิภาพการเรนเดอร์ของแอปพลิเคชัน React โดยเฉพาะอย่างยิ่งแอปพลิเคชันที่ใช้ Concurrent Mode มันถูกรวมเข้ากับส่วนขยายเบราว์เซอร์ React DevTools และให้ข้อมูลเชิงลึกโดยละเอียดเกี่ยวกับวิธีการที่ React เรนเดอร์คอมโพเนนต์ของคุณ
ด้วย Profiler คุณสามารถ:
- ระบุคอมโพเนนต์ที่ทำงานช้า: ระบุคอมโพเนนต์ที่ใช้เวลานานที่สุดในการเรนเดอร์
- วิเคราะห์รูปแบบการเรนเดอร์: ทำความเข้าใจว่า React จัดลำดับความสำคัญและกำหนดเวลาการอัปเดตอย่างไร
- เพิ่มประสิทธิภาพ: ระบุและแก้ไขปัญหาคอขวดด้านประสิทธิภาพเพื่อปรับปรุงการตอบสนอง
การตั้งค่า Profiler
หากต้องการใช้ React Fiber Concurrent Mode Profiler คุณจะต้องมี:
- React DevTools: ติดตั้งส่วนขยายเบราว์เซอร์ React DevTools สำหรับ Chrome, Firefox หรือ Edge
- React 16.4+: ตรวจสอบให้แน่ใจว่าแอปพลิเคชัน React ของคุณใช้ React เวอร์ชัน 16.4 หรือสูงกว่า (โดยหลักการแล้วคือเวอร์ชันล่าสุด)
- Development Mode: Profiler ได้รับการออกแบบมาเพื่อใช้ใน Development Mode เป็นหลัก แม้ว่าคุณจะสามารถสร้างโปรไฟล์การผลิตได้ แต่ผลลัพธ์อาจมีรายละเอียดและความแม่นยำน้อยกว่า
การใช้ Profiler
เมื่อคุณตั้งค่า Profiler แล้ว ให้ทำตามขั้นตอนเหล่านี้เพื่อวิเคราะห์ประสิทธิภาพของแอปพลิเคชันของคุณ:
- เปิด React DevTools: เปิดเครื่องมือสำหรับนักพัฒนาของเบราว์เซอร์ของคุณ แล้วเลือกแท็บ "Profiler"
- เริ่มการบันทึก: คลิกปุ่ม "Record" เพื่อเริ่มการสร้างโปรไฟล์แอปพลิเคชันของคุณ
- โต้ตอบกับแอปพลิเคชันของคุณ: ใช้แอปพลิเคชันของคุณเหมือนกับที่ผู้ใช้ทั่วไปจะทำ ทริกเกอร์การดำเนินการต่างๆ นำทางระหว่างหน้า และโต้ตอบกับคอมโพเนนต์ต่างๆ
- หยุดการบันทึก: คลิกปุ่ม "Stop" เพื่อสิ้นสุดเซสชันการสร้างโปรไฟล์
- วิเคราะห์ผลลัพธ์: Profiler จะแสดงภาพประสิทธิภาพการเรนเดอร์ของแอปพลิเคชันของคุณ
การแสดงภาพของ Profiler
Profiler มีการแสดงภาพหลายแบบเพื่อช่วยให้คุณเข้าใจประสิทธิภาพการเรนเดอร์ของแอปพลิเคชันของคุณ:แผนภูมิเปลวไฟ
แผนภูมิเปลวไฟเป็นการแสดงภาพหลักใน Profiler โดยจะแสดงการแสดงลำดับชั้นของแผนผังคอมโพเนนต์ของคุณ โดยแต่ละแท่งแสดงถึงคอมโพเนนต์และเวลาในการเรนเดอร์ ความกว้างของแท่งสอดคล้องกับระยะเวลาที่ใช้ในการเรนเดอร์คอมโพเนนต์นั้น คอมโพเนนต์ที่สูงกว่าในแผนภูมิคือคอมโพเนนต์หลัก และคอมโพเนนต์ที่ต่ำกว่าในแผนภูมิคือคอมโพเนนต์ลูก ทำให้ง่ายต่อการดูเวลาทั้งหมดที่ใช้ในแต่ละส่วนของแผนผังคอมโพเนนต์ และเพื่อระบุคอมโพเนนต์ที่ใช้เวลานานที่สุดในการเรนเดอร์ได้อย่างรวดเร็ว
การตีความแผนภูมิเปลวไฟ:
- แท่งกว้าง: ระบุคอมโพเนนต์ที่ใช้เวลาในการเรนเดอร์เป็นจำนวนมาก นี่เป็นพื้นที่ที่อาจต้องปรับให้เหมาะสม
- แผนผังลึก: อาจบ่งบอกถึงการซ้อนมากเกินไปหรือการเรนเดอร์ใหม่ที่ไม่จำเป็น
- ช่องว่าง: อาจบ่งบอกถึงเวลาที่ใช้ในการรอข้อมูลหรือการดำเนินการแบบอะซิงโครนัสอื่นๆ
แผนภูมิอันดับ
แผนภูมิอันดับจะแสดงรายการคอมโพเนนต์ที่เรียงตามเวลาในการเรนเดอร์ทั้งหมด ซึ่งจะให้ภาพรวมอย่างรวดเร็วของคอมโพเนนต์ที่มีส่วนทำให้เกิดค่าใช้จ่ายด้านประสิทธิภาพของแอปพลิเคชันของคุณมากที่สุด เป็นจุดเริ่มต้นที่ดีสำหรับการระบุคอมโพเนนต์ที่ต้องปรับให้เหมาะสม
การใช้แผนภูมิอันดับ:
- มุ่งเน้นไปที่คอมโพเนนต์ที่ด้านบนสุดของรายการ เนื่องจากเป็นคอมโพเนนต์ที่มีความสำคัญต่อประสิทธิภาพมากที่สุด
- เปรียบเทียบเวลาในการเรนเดอร์ของคอมโพเนนต์ต่างๆ เพื่อระบุคอมโพเนนต์ที่ทำงานช้าอย่างไม่สมส่วน
แผนภูมิคอมโพเนนต์
แผนภูมิคอมโพเนนต์จะแสดงมุมมองโดยละเอียดของประวัติการเรนเดอร์ของคอมโพเนนต์เดียว โดยจะแสดงวิธีการที่เวลาในการเรนเดอร์ของคอมโพเนนต์แตกต่างกันไปตามเวลา ทำให้คุณสามารถระบุรูปแบบและความสัมพันธ์กับการโต้ตอบของผู้ใช้หรือการเปลี่ยนแปลงข้อมูลที่เฉพาะเจาะจงได้
การวิเคราะห์แผนภูมิคอมโพเนนต์:
- มองหาช่วงเวลาที่เวลาในการเรนเดอร์เพิ่มขึ้น ซึ่งอาจบ่งบอกถึงปัญหาคอขวดด้านประสิทธิภาพ
- เชื่อมโยงเวลาในการเรนเดอร์กับการดำเนินการของผู้ใช้หรือการอัปเดตข้อมูลที่เฉพาะเจาะจง
- เปรียบเทียบเวลาในการเรนเดอร์ของคอมโพเนนต์เวอร์ชันต่างๆ เพื่อติดตามการปรับปรุงประสิทธิภาพ
การโต้ตอบ
มุมมองการโต้ตอบจะเน้นช่วงเวลาที่การโต้ตอบของผู้ใช้ทริกเกอร์การอัปเดต นี่เป็นประโยชน์อย่างยิ่งใน Concurrent Mode เพื่อทำความเข้าใจว่า React จัดลำดับความสำคัญของงานที่เกี่ยวข้องกับอินพุตของผู้ใช้อย่างไร
เทคนิคการเพิ่มประสิทธิภาพ
เมื่อคุณระบุปัญหาคอขวดด้านประสิทธิภาพโดยใช้ Profiler แล้ว คุณสามารถใช้เทคนิคการเพิ่มประสิทธิภาพต่างๆ เพื่อปรับปรุงการตอบสนองของแอปพลิเคชันของคุณได้ นี่คือกลยุทธ์ทั่วไปบางประการ:
1. Memoization
Memoization เป็นเทคนิคที่ทรงพลังในการป้องกันการเรนเดอร์ใหม่ที่ไม่จำเป็น ซึ่งเกี่ยวข้องกับการแคชผลลัพธ์ของการคำนวณที่ซับซ้อน และนำกลับมาใช้ใหม่เมื่อมีการป้อนข้อมูลเดิม ใน React คุณสามารถใช้ React.memo สำหรับคอมโพเนนต์ฟังก์ชันและ shouldComponentUpdate (หรือ PureComponent) สำหรับคอมโพเนนต์คลาสเพื่อใช้ memoization
ตัวอย่าง (React.memo):
const MyComponent = React.memo(function MyComponent(props) {
// ... render logic ...
});
ตัวอย่าง (shouldComponentUpdate):
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// Compare props and state to determine if a re-render is needed
return nextProps.data !== this.props.data;
}
render() {
// ... render logic ...
}
}
ข้อควรพิจารณาด้านสากล: เมื่อทำการ memoizing คอมโพเนนต์ที่แสดงเนื้อหาที่เป็นภาษาท้องถิ่น (เช่น วันที่ ตัวเลข ข้อความ) ตรวจสอบให้แน่ใจว่าคีย์ memoization รวมข้อมูล locale มิฉะนั้น คอมโพเนนต์อาจไม่เรนเดอร์ใหม่เมื่อ locale เปลี่ยนไป
2. Code Splitting
Code splitting เกี่ยวข้องกับการแบ่งโค้ดของแอปพลิเคชันของคุณออกเป็นกลุ่มเล็กลงที่สามารถโหลดได้ตามต้องการ ซึ่งจะช่วยลดเวลาในการโหลดเริ่มต้นและปรับปรุงประสิทธิภาพที่รับรู้ได้ React มีกลไกหลายอย่างสำหรับการแยกโค้ด รวมถึง dynamic imports และ React.lazy
ตัวอย่าง (React.lazy):
const MyComponent = React.lazy(() => import('./MyComponent'));
function MyParentComponent() {
return (
Loading...}>
);
}
การเพิ่มประสิทธิภาพระดับโลก: Code splitting เป็นประโยชน์อย่างยิ่งสำหรับแอปพลิเคชันที่มีฐานโค้ดขนาดใหญ่ หรือแอปพลิเคชันที่รองรับหลายภาษาหรือภูมิภาค การแบ่งโค้ดตามภาษาหรือภูมิภาค คุณสามารถลดขนาดการดาวน์โหลดสำหรับผู้ใช้ในตำแหน่งที่ตั้งเฉพาะได้
3. Virtualization
Virtualization เป็นเทคนิคสำหรับการเรนเดอร์รายการหรือตารางขนาดใหญ่อย่างมีประสิทธิภาพ ซึ่งเกี่ยวข้องกับการเรนเดอร์เฉพาะรายการที่มองเห็นได้ในวิวพอร์ตเท่านั้น แทนที่จะเรนเดอร์รายการทั้งหมดในคราวเดียว ซึ่งสามารถปรับปรุงประสิทธิภาพได้อย่างมากสำหรับแอปพลิเคชันที่แสดงชุดข้อมูลขนาดใหญ่
ไลบรารีเช่น react-window และ react-virtualized มีคอมโพเนนต์สำหรับการใช้ virtualization ในแอปพลิเคชัน React
4. Debouncing และ Throttling
Debouncing และ throttling เป็นเทคนิคสำหรับการจำกัดอัตราการดำเนินการของฟังก์ชัน Debouncing จะหน่วงเวลาการดำเนินการของฟังก์ชันจนกว่าจะผ่านช่วงเวลาที่ไม่ได้ใช้งาน Throttling จะดำเนินการฟังก์ชันอย่างมากหนึ่งครั้งในช่วงเวลาที่กำหนด เทคนิคเหล่านี้สามารถใช้เพื่อป้องกันการเรนเดอร์ใหม่ที่มากเกินไปเพื่อตอบสนองต่ออินพุตของผู้ใช้หรือการเปลี่ยนแปลงข้อมูลที่บ่อย
ตัวอย่าง (Debouncing):
import { debounce } from 'lodash';
function MyComponent() {
const handleInputChange = debounce((value) => {
// Perform expensive operation here
console.log('Input value:', value);
}, 300);
return (
handleInputChange(e.target.value)} />
);
}
ตัวอย่าง (Throttling):
import { throttle } from 'lodash';
function MyComponent() {
const handleScroll = throttle(() => {
// Perform expensive operation here
console.log('Scrolling...');
}, 200);
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [handleScroll]);
return (
Scroll to trigger the throttled function
);
}
5. การเพิ่มประสิทธิภาพการดึงข้อมูล
การดึงข้อมูลที่ไม่มีประสิทธิภาพอาจเป็นแหล่งที่มาหลักของปัญหาคอขวดด้านประสิทธิภาพ พิจารณากลยุทธ์เหล่านี้:
- ใช้กลไกการแคช: แคชข้อมูลที่เข้าถึงบ่อยเพื่อหลีกเลี่ยงการร้องขอเครือข่ายที่ซ้ำซ้อน
- ดึงเฉพาะข้อมูลที่คุณต้องการ: หลีกเลี่ยงการดึงข้อมูลมากเกินไปที่คอมโพเนนต์ไม่ได้ใช้ GraphQL สามารถช่วยได้ที่นี่
- เพิ่มประสิทธิภาพ API endpoints: ทำงานร่วมกับทีมแบ็กเอนด์ของคุณเพื่อเพิ่มประสิทธิภาพ API endpoints เพื่อประสิทธิภาพ
- ใช้ Suspense สำหรับการดึงข้อมูล: ใช้ประโยชน์จาก React Suspense เพื่อจัดการสถานะการโหลดอย่างสวยงาม
6. หลีกเลี่ยงการอัปเดตสถานะที่ไม่จำเป็น
จัดการสถานะของคอมโพเนนต์ของคุณอย่างระมัดระวัง อัปเดตสถานะเฉพาะเมื่อจำเป็นเท่านั้น และหลีกเลี่ยงการอัปเดตสถานะด้วยค่าเดิม ใช้โครงสร้างข้อมูลที่ไม่เปลี่ยนรูปเพื่อลดความซับซ้อนในการจัดการสถานะและป้องกันการกลายพันธุ์โดยไม่ได้ตั้งใจ
7. เพิ่มประสิทธิภาพรูปภาพและเนื้อหา
รูปภาพขนาดใหญ่และเนื้อหาอื่นๆ อาจส่งผลกระทบอย่างมากต่อเวลาในการโหลดหน้า เพิ่มประสิทธิภาพรูปภาพของคุณโดย:
- การบีบอัดรูปภาพ: ใช้เครื่องมือเช่น ImageOptim หรือ TinyPNG เพื่อลดขนาดไฟล์รูปภาพ
- การใช้รูปแบบรูปภาพที่เหมาะสม: ใช้ WebP เพื่อการบีบอัดและคุณภาพที่เหนือกว่าเมื่อเทียบกับ JPEG หรือ PNG
- การโหลดรูปภาพแบบ Lazy: โหลดรูปภาพเฉพาะเมื่อมองเห็นได้ในวิวพอร์ตเท่านั้น
- การใช้ Content Delivery Network (CDN): กระจายเนื้อหาของคุณไปยังเซิร์ฟเวอร์หลายเครื่องเพื่อปรับปรุงความเร็วในการดาวน์โหลดสำหรับผู้ใช้ทั่วโลก
การเพิ่มประสิทธิภาพระดับโลก: พิจารณาใช้ CDN ที่มีเซิร์ฟเวอร์ตั้งอยู่ในหลายภูมิภาคทางภูมิศาสตร์เพื่อให้แน่ใจว่าผู้ใช้ทั่วโลกจะได้รับความเร็วในการดาวน์โหลดที่รวดเร็ว นอกจากนี้ โปรดคำนึงถึงกฎหมายลิขสิทธิ์ของรูปภาพในประเทศต่างๆ เมื่อเลือกรูปภาพสำหรับแอปพลิเคชันของคุณ
8. การจัดการเหตุการณ์ที่มีประสิทธิภาพ
ตรวจสอบให้แน่ใจว่าตัวจัดการเหตุการณ์ของคุณมีประสิทธิภาพ และหลีกเลี่ยงการดำเนินการที่ซับซ้อนภายในตัวจัดการเหล่านั้น Debounce หรือ throttle ตัวจัดการเหตุการณ์หากจำเป็นเพื่อป้องกันการเรนเดอร์ใหม่ที่มากเกินไป
9. ใช้ Production Builds
ปรับใช้ production build ของแอปพลิเคชัน React ของคุณเสมอ Production build ได้รับการปรับให้เหมาะสมเพื่อประสิทธิภาพและโดยทั่วไปจะมีขนาดเล็กกว่า development build ใช้เครื่องมือเช่น create-react-app หรือ Next.js เพื่อสร้าง production build
10. วิเคราะห์ไลบรารีของบุคคลที่สาม
ไลบรารีของบุคคลที่สามบางครั้งอาจทำให้เกิดปัญหาคอขวดด้านประสิทธิภาพ ใช้ Profiler เพื่อวิเคราะห์ประสิทธิภาพของการพึ่งพาของคุณ และระบุไลบรารีใดๆ ที่มีส่วนทำให้เกิดปัญหาด้านประสิทธิภาพ พิจารณาเปลี่ยนหรือเพิ่มประสิทธิภาพไลบรารีที่ทำงานช้าหากจำเป็น
เทคนิคการสร้างโปรไฟล์ขั้นสูง
การสร้างโปรไฟล์ Production Builds
แม้ว่า Profiler จะได้รับการออกแบบมาสำหรับ development mode เป็นหลัก แต่คุณยังสามารถสร้างโปรไฟล์ production build ได้ อย่างไรก็ตาม ผลลัพธ์อาจมีรายละเอียดและความแม่นยำน้อยกว่าเนื่องจากการเพิ่มประสิทธิภาพที่ดำเนินการระหว่างกระบวนการ build หากต้องการสร้างโปรไฟล์ production build คุณจะต้องเปิดใช้งานการสร้างโปรไฟล์ในการกำหนดค่า production build โปรดดูเอกสารประกอบ React สำหรับคำแนะนำเกี่ยวกับวิธีการทำสิ่งนี้
การสร้างโปรไฟล์การโต้ตอบที่เฉพาะเจาะจง
หากต้องการมุ่งเน้นไปที่การโต้ตอบที่เฉพาะเจาะจง คุณสามารถเริ่มและหยุด Profiler รอบๆ การโต้ตอบเหล่านั้น ซึ่งจะช่วยให้คุณแยกคุณลักษณะด้านประสิทธิภาพของการโต้ตอบเหล่านั้น และระบุปัญหาคอขวด
การใช้ Profiler API
React มี Profiler API ที่อนุญาตให้คุณวัดประสิทธิภาพของคอมโพเนนต์หรือส่วนของโค้ดของคุณโดยทางโปรแกรม ซึ่งจะเป็นประโยชน์สำหรับการทำให้การทดสอบประสิทธิภาพเป็นไปโดยอัตโนมัติ หรือสำหรับการรวบรวมข้อมูลประสิทธิภาพโดยละเอียดในสภาพแวดล้อมการผลิต โปรดดูเอกสารประกอบ React สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Profiler API