คุณไม่จำเป็นต้องจัดส่งโค้ดให้ผู้ใช้มากกว่าที่จำเป็น ดังนั้นให้แยกชุดข้อมูลเพื่อไม่ให้เกิดเหตุการณ์นี้
วิธี React.lazy
ช่วยให้การแยกโค้ดแอปพลิเคชัน React ที่ระดับคอมโพเนนต์โดยใช้การนำเข้าแบบไดนามิกเป็นเรื่องง่าย
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
เหตุใดจึงมีประโยชน์
โดยปกติแล้ว แอปพลิเคชัน React ขนาดใหญ่จะประกอบด้วยคอมโพเนนต์ เมธอดยูทิลิตี และไลบรารีของบุคคลที่สามจำนวนมาก หากไม่ได้พยายามโหลด ส่วนต่างๆ ของแอปพลิเคชันเฉพาะเมื่อจำเป็น ระบบจะจัดส่ง JavaScript Bundle ขนาดใหญ่รายการเดียว ให้ผู้ใช้ทันทีที่โหลดหน้าแรก ซึ่งอาจส่งผลต่อประสิทธิภาพของหน้าเว็บอย่างมาก
ฟังก์ชัน React.lazy
มีวิธีในตัวในการแยกคอมโพเนนต์ในแอปพลิเคชันออกเป็น JavaScript หลายๆ ชิ้นโดยไม่ต้องทำอะไรมาก จากนั้นคุณจะจัดการสถานะการโหลดได้เมื่อใช้ร่วมกับคอมโพเนนต์ Suspense
สืบสวน
ปัญหาของการจัดส่งเพย์โหลด JavaScript ขนาดใหญ่ให้ผู้ใช้คือระยะเวลาที่หน้าเว็บจะโหลดเสร็จ โดยเฉพาะอย่างยิ่งในอุปกรณ์ที่มีประสิทธิภาพต่ำกว่าและเครือข่ายที่เชื่อมต่อช้า ด้วยเหตุนี้ การแยกโค้ดและการโหลดแบบ Lazy จึงมีประโยชน์อย่างยิ่ง
อย่างไรก็ตาม จะมีความล่าช้าเล็กน้อยที่ผู้ใช้ต้องพบเมื่อ
มีการดึงข้อมูลคอมโพเนนต์ที่แยกโค้ดผ่านเครือข่าย ดังนั้นจึงควร
แสดงสถานะการโหลดที่มีประโยชน์ การใช้ 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) เพื่อเปิด DevTools
- คลิกแท็บเครือข่าย
- คลิกเมนูแบบเลื่อนลงการควบคุมอัตรา ซึ่งตั้งค่าเป็นไม่มีการควบคุมอัตราโดยค่าเริ่มต้น เลือก 3G เร็ว
- คลิกปุ่มคลิกฉันในแอป
ตอนนี้สัญญาณบอกสถานะการโหลดจะแสดงนานขึ้น สังเกตว่าโค้ดทั้งหมดที่ประกอบกันเป็น AvatarComponent
จะได้รับการดึงข้อมูลเป็นก้อนแยกต่างหาก

การระงับคอมโพเนนต์หลายรายการ
อีกฟีเจอร์หนึ่งของ Suspense
คือการอนุญาตให้คุณระงับการโหลดคอมโพเนนต์หลายรายการ แม้ว่าคอมโพเนนต์ทั้งหมดจะโหลดแบบ Lazy Loading ก็ตาม
เช่น
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 ที่มีการกำหนดเวอร์ชัน
แบบเลซีโหลดซึ่งล้าสมัยและไม่พร้อมใช้งานอีกต่อไปหลังจากการปรับใช้เซิร์ฟเวอร์ใหม่
React มีรูปแบบมาตรฐานสำหรับการจัดการข้อผิดพลาดในการโหลดประเภทนี้อย่างราบรื่น นั่นคือการใช้ขอบเขตข้อผิดพลาด ตามที่อธิบายไว้ในเอกสารประกอบ
คอมโพเนนต์ React ใดก็ได้สามารถทำหน้าที่เป็นขอบเขตข้อผิดพลาดได้หากใช้เมธอดวงจรของคอมโพเนนต์อย่างใดอย่างหนึ่ง (หรือทั้ง 2 อย่าง)
static getDerivedStateFromError()
หรือ
componentDidCatch()
หากต้องการตรวจหาและจัดการข้อผิดพลาดในการโหลดแบบ Lazy Loading คุณสามารถห่อ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
เอกสารประกอบของ React
แสดงวิธีใช้
Suspense
ร่วมกับreact-router
- ระบุคอมโพเนนต์ขนาดใหญ่ในหน้าเว็บของเว็บไซต์ที่แสดงผลเฉพาะเมื่อมีการโต้ตอบของผู้ใช้บางอย่าง (เช่น การคลิกปุ่ม) การแยกคอมโพเนนต์เหล่านี้จะช่วยลดเพย์โหลด JavaScript
- พิจารณาแยกส่วนอื่นๆ ที่อยู่นอกหน้าจอและไม่สำคัญต่อ ผู้ใช้