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