ไทย

ปลดล็อกประสิทธิภาพเว็บที่เร็วยิ่งขึ้นด้วย Selective Hydration ของ React 18 คู่มือฉบับสมบูรณ์นี้จะสำรวจการโหลดตามลำดับความสำคัญ, Streaming SSR และการนำไปใช้จริงสำหรับผู้ใช้ทั่วโลก

React Selective Hydration: เจาะลึกการโหลดคอมโพเนนต์ตามลำดับความสำคัญ

ในการแสวงหาประสิทธิภาพเว็บที่เหนือกว่าอย่างไม่หยุดยั้ง นักพัฒนา frontend ต้องเผชิญกับการตัดสินใจที่ซับซ้อนอยู่เสมอ เราต้องการแอปพลิเคชันที่มีลูกเล่นและโต้ตอบได้ แต่ในขณะเดียวกันก็ต้องการให้มันโหลดได้ทันทีและตอบสนองโดยไม่ล่าช้า ไม่ว่าผู้ใช้จะใช้อุปกรณ์หรือความเร็วเครือข่ายแบบใดก็ตาม เป็นเวลาหลายปีที่ Server-Side Rendering (SSR) เป็นรากฐานสำคัญของความพยายามนี้ โดยช่วยให้หน้าเว็บโหลดครั้งแรกได้เร็วและมีประโยชน์ด้าน SEO ที่แข็งแกร่ง อย่างไรก็ตาม SSR แบบดั้งเดิมก็มาพร้อมกับคอขวดที่สำคัญ นั่นคือปัญหา Hydration แบบ "ทั้งหมดหรือไม่มีเลย" (all-or-nothing) ที่น่าปวดหัว

ก่อนที่หน้าเว็บที่สร้างจาก SSR จะสามารถโต้ตอบได้อย่างแท้จริง ชุดโค้ด JavaScript ทั้งหมดของแอปพลิเคชันจะต้องถูกดาวน์โหลด แยกวิเคราะห์ และประมวลผลเสียก่อน ซึ่งมักจะนำไปสู่ประสบการณ์ผู้ใช้ที่น่าหงุดหงิด ที่หน้าเว็บดูเหมือนจะสมบูรณ์และพร้อมใช้งานแล้ว แต่กลับไม่ตอบสนองต่อการคลิกหรือการป้อนข้อมูลใดๆ ซึ่งเป็นปรากฏการณ์ที่ส่งผลเสียต่อตัวชี้วัดสำคัญอย่าง Time to Interactive (TTI) และตัวชี้วัดใหม่อย่าง Interaction to Next Paint (INP)

และแล้ว React 18 ก็เข้ามา พร้อมกับเอนจิน concurrent rendering ที่เป็นนวัตกรรมใหม่ React ได้นำเสนอวิธีแก้ปัญหาที่ทั้งชาญฉลาดและทรงพลัง นั่นคือ Selective Hydration นี่ไม่ใช่แค่การปรับปรุงเล็กๆ น้อยๆ แต่เป็นการเปลี่ยนแปลงกระบวนทัศน์ขั้นพื้นฐานในวิธีที่แอปพลิเคชัน React กลับมามีชีวิตในเบราว์เซอร์ มันก้าวข้ามโมเดล Hydration แบบ monolithic ไปสู่ระบบที่ละเอียดและอิงตามลำดับความสำคัญซึ่งให้ความสำคัญกับการโต้ตอบของผู้ใช้เป็นอันดับแรก

คู่มือฉบับสมบูรณ์นี้จะสำรวจกลไก ประโยชน์ และการนำ React Selective Hydration ไปใช้จริง เราจะมาแยกส่วนประกอบว่ามันทำงานอย่างไร ทำไมมันถึงเป็นตัวเปลี่ยนเกมสำหรับแอปพลิเคชันระดับโลก และคุณจะใช้ประโยชน์จากมันเพื่อสร้างประสบการณ์ผู้ใช้ที่รวดเร็วและยืดหยุ่นมากขึ้นได้อย่างไร

ทำความเข้าใจอดีต: ความท้าทายของ SSR Hydration แบบดั้งเดิม

เพื่อให้เข้าใจถึงนวัตกรรมของ Selective Hydration อย่างถ่องแท้ เราต้องเข้าใจข้อจำกัดที่มันถูกออกแบบมาเพื่อเอาชนะก่อน ลองย้อนกลับไปดูโลกของ Server-Side Rendering ก่อนยุค React 18 กัน

Server-Side Rendering (SSR) คืออะไร?

ในแอปพลิเคชัน React ที่เรนเดอร์ฝั่งไคลเอ็นต์ (CSR) ทั่วไป เบราว์เซอร์จะได้รับไฟล์ HTML ขนาดเล็กและไฟล์ JavaScript ขนาดใหญ่ จากนั้นเบราว์เซอร์จะประมวลผล JavaScript เพื่อเรนเดอร์เนื้อหาของหน้าเว็บ กระบวนการนี้อาจช้า ทำให้ผู้ใช้ต้องจ้องมองหน้าจอว่างเปล่าและทำให้เครื่องมือค้นหา (search engine crawlers) จัดทำดัชนีเนื้อหาได้ยาก

SSR พลิกโมเดลนี้กลับกัน โดยเซิร์ฟเวอร์จะรันแอปพลิเคชัน React สร้าง HTML ทั้งหมดสำหรับหน้าที่ร้องขอ และส่งไปยังเบราว์เซอร์ ซึ่งมีประโยชน์ในทันที:

ปัญหาคอขวดของ Hydration แบบ "ทั้งหมดหรือไม่มีเลย"

แม้ว่า HTML เริ่มต้นจาก SSR จะให้การแสดงผลตัวอย่างแบบไม่โต้ตอบที่รวดเร็ว แต่หน้าเว็บยังไม่สามารถใช้งานได้อย่างแท้จริง Event handler (เช่น `onClick`) และการจัดการ state ที่กำหนดไว้ในคอมโพเนนต์ React ของคุณยังไม่มีอยู่ กระบวนการในการแนบตรรกะ JavaScript นี้เข้ากับ HTML ที่สร้างจากเซิร์ฟเวอร์เรียกว่า hydration

นี่คือปัญหาคลาสสิก: Hydration แบบดั้งเดิมเป็นกระบวนการที่ทำงานเป็นก้อนเดียว (monolithic) พร้อมกัน (synchronous) และปิดกั้นการทำงานอื่น (blocking) มันดำเนินไปตามลำดับที่เข้มงวดและไม่ยืดหยุ่น:

  1. ต้องดาวน์โหลด JavaScript bundle ทั้งหมดสำหรับทั้งหน้าเว็บ
  2. React ต้องแยกวิเคราะห์และประมวลผล bundle ทั้งหมด
  3. จากนั้น React จะไล่ไปตาม component tree ทั้งหมดจากราก เพื่อแนบ event listeners และตั้งค่า state สำหรับทุกๆ คอมโพเนนต์
  4. หน้าเว็บจะสามารถโต้ตอบได้ก็ต่อเมื่อกระบวนการทั้งหมดนี้เสร็จสิ้นแล้วเท่านั้น

ลองจินตนาการว่าคุณได้รับรถคันใหม่ที่ประกอบเสร็จอย่างสวยงาม แต่มีคนบอกว่าคุณไม่สามารถเปิดประตู สตาร์ทเครื่องยนต์ หรือแม้แต่บีบแตรได้ จนกว่าสวิตช์หลักสำหรับระบบไฟฟ้าทั้งหมดของรถจะถูกเปิด แม้ว่าคุณจะแค่ต้องการหยิบกระเป๋าจากเบาะข้างคนขับ คุณก็ต้องรอทุกอย่าง นี่คือประสบการณ์ผู้ใช้ของ Hydration แบบดั้งเดิม หน้าเว็บอาจดูพร้อมใช้งาน แต่ความพยายามใดๆ ที่จะโต้ตอบกับมันจะไม่มีอะไรเกิดขึ้น นำไปสู่ความสับสนของผู้ใช้และ "การคลิกด้วยความโมโห" (rage clicks)

เข้าสู่ React 18: การเปลี่ยนแปลงกระบวนทัศน์ด้วย Concurrent Rendering

นวัตกรรมหลักของ React 18 คือ concurrency ซึ่งช่วยให้ React สามารถเตรียมการอัปเดต state หลายรายการพร้อมกัน และสามารถหยุดชั่วคราว ดำเนินการต่อ หรือยกเลิกงานเรนเดอร์ได้โดยไม่ปิดกั้น main thread แม้ว่าสิ่งนี้จะส่งผลกระทบอย่างลึกซึ้งต่อการเรนเดอร์ฝั่งไคลเอ็นต์ แต่มันคือกุญแจสำคัญที่ปลดล็อกสถาปัตยกรรมการเรนเดอร์บนเซิร์ฟเวอร์ที่ชาญฉลาดขึ้นมาก

Concurrency ทำให้เกิดคุณสมบัติที่สำคัญสองอย่างที่ทำงานควบคู่กันเพื่อให้ Selective Hydration เป็นไปได้:

  1. Streaming SSR: เซิร์ฟเวอร์สามารถส่ง HTML เป็นส่วนๆ (chunks) ขณะที่กำลังเรนเดอร์ แทนที่จะต้องรอให้ทั้งหน้าพร้อม
  2. Selective Hydration: React สามารถเริ่มทำ hydration หน้าเว็บได้ก่อนที่ HTML stream ทั้งหมดและ JavaScript ทั้งหมดจะมาถึง และสามารถทำได้ในลักษณะที่ไม่ปิดกั้นและจัดลำดับความสำคัญได้

แนวคิดหลัก: Selective Hydration คืออะไร?

Selective Hydration รื้อโมเดล "ทั้งหมดหรือไม่มีเลย" ทิ้งไป แทนที่จะเป็นงานขนาดใหญ่ก้อนเดียว hydration จะกลายเป็นชุดของงานที่เล็กลง จัดการได้ และจัดลำดับความสำคัญได้ มันช่วยให้ React สามารถทำ hydration คอมโพเนนต์ต่างๆ เมื่อพร้อมใช้งาน และที่สำคัญที่สุดคือสามารถจัดลำดับความสำคัญของคอมโพเนนต์ที่ผู้ใช้กำลังพยายามโต้ตอบด้วย

ส่วนผสมสำคัญ: Streaming SSR และ ``

เพื่อให้เข้าใจ Selective Hydration คุณต้องเข้าใจเสาหลักสองประการของมันก่อน นั่นคือ Streaming SSR และคอมโพเนนต์ ``

Streaming SSR

ด้วย Streaming SSR เซิร์ฟเวอร์ไม่จำเป็นต้องรอการดึงข้อมูลที่ช้า (เช่น การเรียก API สำหรับส่วนความคิดเห็น) ให้เสร็จสิ้นก่อนที่จะส่ง HTML เริ่มต้น แต่สามารถส่ง HTML สำหรับส่วนต่างๆ ของหน้าที่พร้อมแล้วได้ทันที เช่น โครงสร้างหลักและเนื้อหา สำหรับส่วนที่ช้ากว่า มันจะส่งตัวยึดตำแหน่ง (placeholder) ซึ่งก็คือ UI สำรอง (fallback UI) เมื่อข้อมูลสำหรับส่วนที่ช้าพร้อมแล้ว เซิร์ฟเวอร์จะสตรีม HTML เพิ่มเติมและสคริปต์แบบ inline เพื่อแทนที่ตัวยึดตำแหน่งด้วยเนื้อหาจริง ซึ่งหมายความว่าผู้ใช้จะเห็นโครงสร้างหน้าและเนื้อหาหลักได้เร็วขึ้นมาก

ขอบเขตของ ``

คอมโพเนนต์ `` คือกลไกที่คุณใช้เพื่อบอก React ว่าส่วนใดของแอปพลิเคชันของคุณที่สามารถโหลดแบบอะซิงโครนัสได้โดยไม่ปิดกั้นส่วนที่เหลือของหน้า คุณครอบคอมโพเนนต์ที่ช้าด้วย `` และระบุ `fallback` prop ซึ่งเป็นสิ่งที่ React จะเรนเดอร์ในขณะที่คอมโพเนนต์กำลังโหลด

บนเซิร์ฟเวอร์ `` เป็นสัญญาณสำหรับการสตรีม เมื่อเซิร์ฟเวอร์พบขอบเขตของ `` มันจะรู้ว่าสามารถส่ง HTML ของ fallback ก่อน แล้วค่อยสตรีม HTML ของคอมโพเนนต์จริงในภายหลังเมื่อพร้อม ในเบราว์เซอร์ ขอบเขตของ `` จะกำหนด "เกาะ" (islands) ที่สามารถทำ hydration ได้อย่างอิสระ

นี่คือตัวอย่างเชิงแนวคิด:


function App() {
  return (
    <div>
      <Header />
      <main>
        <ArticleContent />
        <Suspense fallback={<CommentsSkeleton />}>
          <CommentsSection />  <!-- คอมโพเนนต์นี้อาจดึงข้อมูล -->
        </Suspense>
      </main>
      <Suspense fallback={<ChatWidgetLoader />}>
        <ChatWidget /> <!-- นี่คือสคริปต์ของบุคคลที่สามที่หนัก -->
      </Suspense>
      <Footer />
    </div>
  );
}

ในตัวอย่างนี้ `Header`, `ArticleContent` และ `Footer` จะถูกเรนเดอร์และสตรีมทันที เบราว์เซอร์จะได้รับ HTML สำหรับ `CommentsSkeleton` และ `ChatWidgetLoader` หลังจากนั้น เมื่อ `CommentsSection` และ `ChatWidget` พร้อมบนเซิร์ฟเวอร์ HTML ของพวกมันจะถูกสตรีมลงมายังไคลเอ็นต์ ขอบเขต `` เหล่านี้สร้างรอยต่อที่ช่วยให้ Selective Hydration ทำงานได้อย่างมหัศจรรย์

มันทำงานอย่างไร: การโหลดตามลำดับความสำคัญในทางปฏิบัติ

ความยอดเยี่ยมที่แท้จริงของ Selective Hydration อยู่ที่วิธีที่มันใช้การโต้ตอบของผู้ใช้เพื่อกำหนดลำดับการทำงาน React จะไม่ทำตามสคริปต์ hydration แบบบนลงล่างที่ตายตัวอีกต่อไป แต่มันจะตอบสนองแบบไดนามิกต่อผู้ใช้

ผู้ใช้คือสิ่งสำคัญที่สุด

นี่คือหลักการสำคัญ: React จัดลำดับความสำคัญในการทำ hydration ให้กับคอมโพเนนต์ที่ผู้ใช้โต้ตอบด้วย

ในขณะที่ React กำลังทำ hydration หน้าเว็บ มันจะแนบ event listeners ไว้ที่ระดับราก (root) หากผู้ใช้คลิกที่ปุ่มภายในคอมโพเนนต์ที่ยังไม่ได้รับการทำ hydration React จะทำสิ่งที่ฉลาดอย่างเหลือเชื่อ:

  1. การดักจับ Event: React ดักจับ event การคลิกที่ root
  2. การจัดลำดับความสำคัญ: มันระบุว่าผู้ใช้คลิกที่คอมโพเนนต์ใด จากนั้นจึงเพิ่มระดับความสำคัญของการทำ hydration ของคอมโพเนนต์นั้นและคอมโพเนนต์แม่ของมัน งาน hydration ที่มีความสำคัญต่ำกว่าที่กำลังดำเนินอยู่จะถูกหยุดชั่วคราว
  3. ทำ Hydration และเล่นซ้ำ: React จะรีบทำ hydration คอมโพเนนต์เป้าหมายอย่างเร่งด่วน เมื่อ hydration เสร็จสมบูรณ์และ `onClick` handler ถูกแนบแล้ว React จะเล่น event การคลิกที่ดักจับไว้ซ้ำอีกครั้ง

จากมุมมองของผู้ใช้ การโต้ตอบนั้นก็ใช้งานได้เลย ราวกับว่าคอมโพเนนต์นั้นโต้ตอบได้ตั้งแต่แรก พวกเขาไม่รู้เลยว่าเบื้องหลังมีการจัดลำดับความสำคัญที่ซับซ้อนเกิดขึ้นเพื่อให้มันเกิดขึ้นได้ทันที

สถานการณ์ทีละขั้นตอน

ลองมาดูตัวอย่างหน้า e-commerce ของเราเพื่อดูการทำงานจริง หน้านี้มีตารางแสดงสินค้าหลัก, แถบด้านข้างพร้อมตัวกรองที่ซับซ้อน และวิดเจ็ตแชทของบุคคลที่สามที่หนักหน่วงอยู่ด้านล่าง

  1. การสตรีมจากเซิร์ฟเวอร์: เซิร์ฟเวอร์ส่งโครง HTML เริ่มต้น รวมถึงตารางแสดงสินค้า แถบด้านข้างและวิดเจ็ตแชทถูกครอบด้วย `` และ UI สำรองของพวกมัน (skeletons/loaders) จะถูกส่งมา
  2. การเรนเดอร์ครั้งแรก: เบราว์เซอร์เรนเดอร์ตารางแสดงสินค้า ผู้ใช้สามารถเห็นสินค้าได้เกือบจะในทันที TTI ยังคงสูงอยู่เพราะยังไม่มี JavaScript ใดๆ ถูกแนบ
  3. การโหลดโค้ด: JavaScript bundles เริ่มดาวน์โหลด สมมติว่าโค้ดสำหรับแถบด้านข้างและวิดเจ็ตแชทอยู่ในไฟล์แยกกัน (code-split chunks)
  4. การโต้ตอบของผู้ใช้: ก่อนที่ทุกอย่างจะทำ hydration เสร็จสิ้น ผู้ใช้เห็นสินค้าที่ชอบและคลิกปุ่ม "เพิ่มลงในรถเข็น" ภายในตารางแสดงสินค้า
  5. ความมหัศจรรย์ของการจัดลำดับความสำคัญ: React ดักจับการคลิก มันเห็นว่าการคลิกเกิดขึ้นภายในคอมโพเนนต์ `ProductGrid` มันจะยกเลิกหรือหยุดการทำ hydration ของส่วนอื่นๆ ของหน้า (ซึ่งอาจจะเพิ่งเริ่มไป) และมุ่งเน้นไปที่การทำ hydration ของ `ProductGrid` โดยเฉพาะ
  6. การโต้ตอบที่รวดเร็ว: คอมโพเนนต์ `ProductGrid` ทำ hydration ได้อย่างรวดเร็วมากเพราะโค้ดของมันน่าจะอยู่ใน bundle หลัก `onClick` handler ถูกแนบ และ event การคลิกที่ดักจับไว้จะถูกเล่นซ้ำ สินค้าจะถูกเพิ่มลงในรถเข็น ผู้ใช้ได้รับการตอบสนองทันที
  7. การทำ Hydration ต่อ: ตอนนี้เมื่อการโต้ตอบที่มีความสำคัญสูงได้รับการจัดการแล้ว React ก็จะกลับมาทำงานต่อ มันจะดำเนินการทำ hydration แถบด้านข้างต่อไป สุดท้าย เมื่อโค้ดสำหรับวิดเจ็ตแชทมาถึง มันก็จะทำ hydration คอมโพเนนต์นั้นเป็นลำดับสุดท้าย

ผลลัพธ์? TTI สำหรับส่วนที่สำคัญที่สุดของหน้าเว็บนั้นเกิดขึ้นเกือบจะในทันที โดยขับเคลื่อนจากความตั้งใจของผู้ใช้เอง TTI โดยรวมของหน้าเว็บไม่ใช่ตัวเลขที่น่ากลัวเพียงตัวเดียวอีกต่อไป แต่เป็นกระบวนการที่ค่อยเป็นค่อยไปและยึดผู้ใช้เป็นศูนย์กลาง

ประโยชน์ที่จับต้องได้สำหรับผู้ใช้ทั่วโลก

ผลกระทบของ Selective Hydration นั้นลึกซึ้ง โดยเฉพาะอย่างยิ่งสำหรับแอปพลิเคชันที่ให้บริการแก่ผู้ใช้ทั่วโลกที่มีความหลากหลาย ทั้งในด้านเงื่อนไขเครือข่ายและความสามารถของอุปกรณ์

ประสิทธิภาพที่รับรู้ได้ดีขึ้นอย่างมาก

ประโยชน์ที่สำคัญที่สุดคือการปรับปรุงประสิทธิภาพที่ผู้ใช้รับรู้ได้อย่างมหาศาล ด้วยการทำให้ส่วนต่างๆ ของหน้าที่ผู้ใช้โต้ตอบด้วยพร้อมใช้งานก่อน แอปพลิเคชันจะ*รู้สึก*เร็วขึ้น นี่เป็นสิ่งสำคัญอย่างยิ่งสำหรับการรักษาผู้ใช้ สำหรับผู้ใช้บนเครือข่าย 3G ที่ช้าในประเทศกำลังพัฒนา ความแตกต่างระหว่างการรอ 15 วินาทีเพื่อให้ทั้งหน้าเว็บสามารถโต้ตอบได้ กับการที่สามารถโต้ตอบกับเนื้อหาหลักได้ใน 3 วินาทีนั้นมหาศาล

Core Web Vitals ที่ดีขึ้น

Selective Hydration ส่งผลโดยตรงต่อ Core Web Vitals ของ Google:

การแยกเนื้อหาออกจากคอมโพเนนต์ที่หนัก

เว็บแอปสมัยใหม่มักเต็มไปด้วยสคริปต์ของบุคคลที่สามที่หนักหน่วงสำหรับ analytics, A/B testing, แชทสนับสนุนลูกค้า หรือการโฆษณา ในอดีต สคริปต์เหล่านี้สามารถปิดกั้นทั้งแอปพลิเคชันไม่ให้โต้ตอบได้ ด้วย Selective Hydration และ `` คอมโพเนนต์ที่ไม่สำคัญเหล่านี้สามารถถูกแยกออกไปได้อย่างสมบูรณ์ เนื้อหาหลักของแอปพลิเคชันสามารถโหลดและโต้ตอบได้ในขณะที่สคริปต์หนักๆ เหล่านี้โหลดและทำ hydration อยู่เบื้องหลัง โดยไม่ส่งผลกระทบต่อประสบการณ์ผู้ใช้หลัก

แอปพลิเคชันที่ยืดหยุ่นมากขึ้น

เนื่องจาก hydration สามารถเกิดขึ้นเป็นส่วนๆ ได้ ข้อผิดพลาดในคอมโพเนนต์ที่ไม่จำเป็น (เช่น วิดเจ็ตโซเชียลมีเดีย) จะไม่ทำให้ทั้งหน้าเว็บพังเสมอไป React อาจสามารถแยกข้อผิดพลาดไว้ภายในขอบเขต `` นั้น ในขณะที่ส่วนที่เหลือของแอปพลิเคชันยังคงโต้ตอบได้

การนำไปใช้จริงและแนวทางปฏิบัติที่ดีที่สุด

การนำ Selective Hydration มาใช้เป็นเรื่องของการจัดโครงสร้างแอปพลิเคชันของคุณให้ถูกต้องมากกว่าการเขียนโค้ดใหม่ที่ซับซ้อน เฟรมเวิร์กสมัยใหม่เช่น Next.js (ด้วย App Router) และ Remix จะจัดการการตั้งค่าเซิร์ฟเวอร์ส่วนใหญ่ให้คุณ แต่การเข้าใจหลักการสำคัญเป็นกุญแจสำคัญ

การใช้ `hydrateRoot` API

ทางฝั่งไคลเอ็นต์ จุดเริ่มต้นสำหรับพฤติกรรมใหม่นี้คือ `hydrateRoot` API คุณจะต้องเปลี่ยนจาก `ReactDOM.hydrate` แบบเก่าไปเป็น `ReactDOM.hydrateRoot`


// ก่อนหน้า (Legacy)
import { hydrate } from 'react-dom';
const container = document.getElementById('root');
hydrate(<App />, container);

// ปัจจุบัน (React 18+)
import { hydrateRoot } from 'react-dom/client';
const container = document.getElementById('root');
const root = hydrateRoot(container, <App />);

การเปลี่ยนแปลงง่ายๆ นี้จะทำให้แอปพลิเคชันของคุณเปิดใช้งานคุณสมบัติ concurrent rendering ใหม่ รวมถึง Selective Hydration ด้วย

การใช้ `` อย่างมีกลยุทธ์

พลังของ Selective Hydration จะถูกปลดล็อกโดยวิธีที่คุณวางขอบเขต `` ของคุณ อย่าครอบทุกคอมโพเนนต์เล็กๆ แต่ให้คิดในแง่ของหน่วย UI ที่มีเหตุผลหรือ "เกาะ" ที่สามารถโหลดได้อย่างอิสระโดยไม่รบกวนขั้นตอนการใช้งานของผู้ใช้

ตัวเลือกที่ดีสำหรับขอบเขต `` ได้แก่:

ใช้ร่วมกับ `React.lazy` เพื่อทำ Code Splitting

Selective Hydration จะทรงพลังยิ่งขึ้นเมื่อใช้ร่วมกับ code splitting ผ่าน `React.lazy` สิ่งนี้ทำให้มั่นใจได้ว่า JavaScript สำหรับคอมโพเนนต์ที่มีความสำคัญต่ำของคุณจะไม่ถูกดาวน์โหลดจนกว่าจะมีความจำเป็น ซึ่งจะช่วยลดขนาด bundle เริ่มต้นลงไปอีก


import React, { Suspense, lazy } from 'react';

const CommentsSection = lazy(() => import('./CommentsSection'));
const ChatWidget = lazy(() => import('./ChatWidget'));

function App() {
  return (
    <div>
      <ArticleContent />
      <Suspense fallback={<CommentsSkeleton />}>
        <CommentsSection />
      </Suspense>
      <Suspense fallback={null}> <!-- ไม่จำเป็นต้องมี loader ที่มองเห็นได้สำหรับวิดเจ็ตที่ซ่อนอยู่ -->
        <ChatWidget />
      </Suspense>
    </div>
  );
}

ในการตั้งค่านี้ โค้ด JavaScript สำหรับ `CommentsSection` และ `ChatWidget` จะอยู่ในไฟล์แยกต่างหาก เบราว์เซอร์จะดึงข้อมูลเหล่านั้นก็ต่อเมื่อ React ตัดสินใจที่จะเรนเดอร์พวกมัน และพวกมันจะทำ hydration อย่างอิสระโดยไม่ปิดกั้น `ArticleContent` หลัก

การตั้งค่าฝั่งเซิร์ฟเวอร์ด้วย `renderToPipeableStream`

สำหรับผู้ที่สร้างโซลูชัน SSR เอง API ฝั่งเซิร์ฟเวอร์ที่ต้องใช้คือ `renderToPipeableStream` API นี้ออกแบบมาโดยเฉพาะสำหรับการสตรีมและทำงานร่วมกับ `` ได้อย่างราบรื่น มันให้คุณควบคุมได้อย่างละเอียดว่าจะส่ง HTML เมื่อใดและจะจัดการกับข้อผิดพลาดอย่างไร อย่างไรก็ตาม สำหรับนักพัฒนาส่วนใหญ่ meta-framework อย่าง Next.js เป็นเส้นทางที่แนะนำ เนื่องจากมันช่วยลดความซับซ้อนนี้ลงไป

อนาคต: React Server Components

Selective Hydration เป็นก้าวที่ยิ่งใหญ่ แต่ก็เป็นส่วนหนึ่งของเรื่องราวที่ใหญ่กว่านั้น วิวัฒนาการขั้นต่อไปคือ React Server Components (RSCs) RSCs คือคอมโพเนนต์ที่ทำงานเฉพาะบนเซิร์ฟเวอร์และไม่เคยส่ง JavaScript ของตนไปยังไคลเอ็นต์ ซึ่งหมายความว่าพวกมันไม่จำเป็นต้องทำ hydration เลย ทำให้ JavaScript bundle ฝั่งไคลเอ็นต์ลดลงไปอีก

Selective Hydration และ RSCs ทำงานร่วมกันได้อย่างสมบูรณ์แบบ ส่วนต่างๆ ของแอปของคุณที่เป็นเพียงการแสดงข้อมูลสามารถเป็น RSCs ได้ (ไม่มี JS ฝั่งไคลเอ็นต์) ในขณะที่ส่วนที่ต้องโต้ตอบสามารถเป็น Client Components ที่ได้รับประโยชน์จาก Selective Hydration การผสมผสานนี้แสดงถึงอนาคตของการสร้างแอปพลิเคชันที่มีประสิทธิภาพสูงและโต้ตอบได้ด้วย React

สรุป: ทำ Hydration อย่างชาญฉลาด ไม่ใช่หนักหน่วง

Selective Hydration ของ React เป็นมากกว่าการเพิ่มประสิทธิภาพ แต่เป็นการเปลี่ยนแปลงพื้นฐานไปสู่สถาปัตยกรรมที่ยึดผู้ใช้เป็นศูนย์กลางมากขึ้น ด้วยการหลุดพ้นจากข้อจำกัดแบบ "ทั้งหมดหรือไม่มีเลย" ในอดีต React 18 ช่วยให้นักพัฒนาสามารถสร้างแอปพลิเคชันที่ไม่เพียงแต่โหลดเร็ว แต่ยังโต้ตอบได้เร็ว แม้ในสภาวะเครือข่ายที่ท้าทาย

ประเด็นสำคัญที่ได้นั้นชัดเจน:

ในฐานะนักพัฒนาที่สร้างสรรค์เพื่อผู้ใช้ทั่วโลก เป้าหมายของเราคือการสร้างประสบการณ์ที่เข้าถึงได้ ยืดหยุ่น และน่าพึงพอใจสำหรับทุกคน ด้วยการยอมรับพลังของ Selective Hydration เราสามารถหยุดทำให้ผู้ใช้ต้องรอและเริ่มส่งมอบตามคำสัญญานั้นได้ ทีละคอมโพเนนต์ตามลำดับความสำคัญ