คุณไม่จำเป็นต้องส่งโค้ดให้ผู้ใช้เกินความจำเป็น ดังนั้นให้แยกกลุ่มเพื่อให้มั่นใจว่าจะไม่เกิดกรณีเช่นนี้
เมธอด React.lazy
ช่วยให้แยกโค้ดแอปพลิเคชัน React ในระดับคอมโพเนนต์ได้ง่ายๆ โดยใช้การนําเข้าแบบไดนามิก
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
เหตุใดจึงมีประโยชน์
แอปพลิเคชัน React ขนาดใหญ่มักจะประกอบด้วยคอมโพเนนต์ ยูทิลิตี และไลบรารีของบุคคลที่สามจำนวนมาก หากไม่มีการพยายามโหลดส่วนต่างๆ ของแอปพลิเคชันเฉพาะเมื่อจําเป็น ระบบจะส่ง JavaScript จำนวนมากชุดเดียวไปยังผู้ใช้ทันทีที่โหลดหน้าแรก ซึ่งอาจส่งผลต่อประสิทธิภาพของหน้าเว็บอย่างมาก
ฟังก์ชัน React.lazy
มีวิธีแยกคอมโพเนนต์ในแอปพลิเคชันออกเป็นกลุ่ม JavaScript แยกต่างหากในตัวโดยที่คุณไม่ต้องทำอะไรมาก จากนั้นคุณก็จัดการสถานะการโหลดได้เมื่อใช้ร่วมกับคอมโพเนนต์ Suspense
สืบสวน
ปัญหาในการส่งเพย์โหลด JavaScript ขนาดใหญ่ไปยังผู้ใช้คือระยะเวลาที่ใช้ในการโหลดหน้าเว็บจนเสร็จสมบูรณ์ โดยเฉพาะอย่างยิ่งในอุปกรณ์และการเชื่อมต่อเครือข่ายที่มีประสิทธิภาพต่ำ ด้วยเหตุนี้ การแยกโค้ดและการโหลดแบบเลื่อนจึงมีประโยชน์อย่างยิ่ง
อย่างไรก็ตาม ผู้ใช้จะพบกับความล่าช้าเล็กน้อยเสมอเมื่อมีการดึงข้อมูลคอมโพเนนต์ที่มีการแยกโค้ดผ่านเครือข่าย จึงจำเป็นต้องแสดงสถานะการโหลดที่เป็นประโยชน์ การใช้ React.lazy
กับคอมโพเนนต์ Suspense
ช่วยแก้ปัญหานี้ได้
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
</Suspense>
)
Suspense
ยอมรับคอมโพเนนต์ fallback
ซึ่งช่วยให้คุณแสดงคอมโพเนนต์ React เป็นสถานะการโหลดได้ ตัวอย่างต่อไปนี้แสดงวิธีการทํางาน
ระบบจะแสดงผลรูปโปรไฟล์ก็ต่อเมื่อมีการคลิกปุ่มเท่านั้น จากนั้นระบบจะส่งคำขอเพื่อดึงข้อมูลโค้ดที่จำเป็นสำหรับ AvatarComponent
ที่ถูกระงับ
ในระหว่างนี้ ระบบจะแสดงคอมโพเนนต์การโหลดสำรอง
ในส่วนนี้ โค้ดที่ประกอบเป็น AvatarComponent
มีขนาดเล็ก ซึ่งเป็นเหตุผลที่ภาพเคลื่อนไหวที่แสดงการโหลดจะแสดงเพียงระยะเวลาสั้นๆ ส่วนประกอบขนาดใหญ่อาจใช้เวลาโหลดนานกว่ามาก โดยเฉพาะเมื่อเชื่อมต่อเครือข่ายที่สัญญาณอ่อน
ตัวอย่างที่แสดงให้เห็นวิธีการทำงานมีดังนี้
- หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ
- กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
- คลิกแท็บเครือข่าย
- คลิกเมนูแบบเลื่อนลงการจำกัด ซึ่งตั้งค่าเป็นไม่มีการจำกัดโดยค่าเริ่มต้น เลือก Fast 3G
- คลิกปุ่ม Click Me ในแอป
สัญญาณบอกสถานะการโหลดจะแสดงนานขึ้น โปรดสังเกตว่าระบบดึงข้อมูลโค้ดทั้งหมดที่ประกอบเป็น AvatarComponent
เป็นกลุ่มแยกต่างหาก
การระงับคอมโพเนนต์หลายรายการ
ฟีเจอร์อีกอย่างของ Suspense
คือช่วยให้คุณระงับการโหลดคอมโพเนนต์หลายรายการได้แม้ว่าจะโหลดแบบ Lazy Load ทั้งหมด
เช่น
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
)
วิธีนี้เป็นวิธีที่มีประโยชน์อย่างยิ่งในการเลื่อนเวลาการแสดงผลของคอมโพเนนต์หลายรายการในขณะที่แสดงสถานะการโหลดเพียงสถานะเดียว เมื่อคอมโพเนนต์ทั้งหมดดึงข้อมูลเสร็จแล้ว ผู้ใช้จะเห็นคอมโพเนนต์ทั้งหมดแสดงพร้อมกัน
คุณดูข้อมูลนี้ได้ด้วยการฝังต่อไปนี้
หากไม่มีขั้นตอนนี้ คุณอาจพบปัญหาการโหลดแบบสลับ หรือ UI โหลดส่วนต่างๆ ตามลำดับโดยแต่ละส่วนมีตัวบ่งชี้การโหลดของตัวเอง ซึ่งอาจทำให้ประสบการณ์ของผู้ใช้ดูกระอักกระอ่วนมากขึ้น
จัดการกับการโหลดไม่สําเร็จ
Suspense
ช่วยให้คุณแสดงสถานะการโหลดชั่วคราวได้ขณะที่ระบบส่งคำขอเครือข่ายอยู่เบื้องหลัง แต่จะเกิดอะไรขึ้นหากคำขอเครือข่ายเหล่านั้นไม่สำเร็จเนื่องจากเหตุผลบางอย่าง คุณอาจออฟไลน์อยู่ หรือเว็บแอปอาจพยายามโหลดURL ที่มีเวอร์ชันแบบ Lazy Load ซึ่งล้าสมัยและไม่พร้อมใช้งานอีกต่อไปหลังจากการนําเซิร์ฟเวอร์กลับมาใช้งานอีกครั้ง
React มีรูปแบบมาตรฐานในการจัดการการโหลดที่ไม่สําเร็จประเภทเหล่านี้อย่างราบรื่นโดยใช้ขอบเขตข้อผิดพลาด ดังที่อธิบายไว้ในเอกสารประกอบ คอมโพเนนต์ React ใดๆ สามารถใช้เป็นขอบเขตข้อผิดพลาดได้หากใช้เมธอดวงจรชีวิตของ static getDerivedStateFromError()
หรือ componentDidCatch()
(หรือทั้ง 2 อย่าง)
หากต้องการตรวจหาและจัดการการโหลดแบบเลื่อนเวลาไว้ทีหลังที่ไม่สําเร็จ คุณสามารถรวมSuspense
คอมโพเนนต์เข้ากับคอมโพเนนต์หลักที่ทำหน้าที่เป็นขอบเขตข้อผิดพลาด ในเมธอด render()
ของขอบเขตข้อผิดพลาด คุณสามารถแสดงผลรายการย่อยตามที่เป็นอยู่หากไม่มีข้อผิดพลาด หรือแสดงผลข้อความแสดงข้อผิดพลาดที่กําหนดเองหากเกิดข้อผิดพลาด
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));
const renderLoader = () => <p>Loading</p>;
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {hasError: false};
}
static getDerivedStateFromError(error) {
return {hasError: true};
}
render() {
if (this.state.hasError) {
return <p>Loading failed! Please reload.</p>;
}
return this.props.children;
}
}
const DetailsComponent = () => (
<ErrorBoundary>
<Suspense fallback={renderLoader()}>
<AvatarComponent />
<InfoComponent />
<MoreInfoComponent />
</Suspense>
</ErrorBoundary>
)
บทสรุป
หากไม่แน่ใจว่าควรเริ่มใช้การแยกโค้ดกับแอปพลิเคชัน React ตรงจุดใด ให้ทำตามขั้นตอนต่อไปนี้
- เริ่มต้นที่ระดับเส้นทาง เส้นทางเป็นวิธีที่ง่ายที่สุดในการระบุจุดของแอปพลิเคชันที่สามารถแยก เอกสาร React จะแสดงวิธีใช้
Suspense
ร่วมกับreact-router
- ระบุคอมโพเนนต์ขนาดใหญ่ในหน้าเว็บของเว็บไซต์ที่แสดงผลเฉพาะเมื่อผู้ใช้โต้ตอบบางอย่าง (เช่น การคลิกปุ่ม) การแยกคอมโพเนนต์เหล่านี้จะช่วยลดเพย์โหลด JavaScript
- พิจารณาแยกเนื้อหาอื่นๆ ที่ไม่ได้แสดงบนหน้าจอและไม่สำคัญต่อผู้ใช้