RSC สำหรับนักพัฒนา Astro
(overreacted.io)- Astro และ React Server Components(RSC) ต่างก็ทำการแยกโค้ดฝั่งเซิร์ฟเวอร์และไคลเอนต์ในลักษณะที่คล้ายกัน
- ใน Astro มี Astro Component และ Client Island ที่แบ่งหน้าที่การทำงานกันคนละส่วน
- RSC แบ่งแนวคิดเดียวกันนี้ออกเป็น Server Component และ Client Component และกำหนดขอบเขตด้วยคำสั่ง
'use client' - เมื่อเทียบกับ Astro แล้ว RSC มีความยืดหยุ่นมากกว่าในการประกอบ UI แบบโต้ตอบและการแชร์โค้ด
- ทั้งสองโมเดลต่างมีโครงสร้างที่ข้อมูลไหลทางเดียวจากเซิร์ฟเวอร์ไปยังไคลเอนต์
บทนำและแนวคิดพื้นฐาน
- Astro มีคอมโพเนนต์หลักอยู่ 2 ประเภทคือ Astro Component และ Client Island
- Astro Component ใช้นามสกุล
.astroและจะทำงานเฉพาะบนเซิร์ฟเวอร์หรือในช่วง build time เท่านั้น จึงสามารถทำงานที่ฝั่งไคลเอนต์ทำไม่ได้ เช่น เข้าถึงระบบไฟล์, query ฐานข้อมูล, หรือเรียกใช้บริการภายใน - Client Island คือคอมโพเนนต์สำหรับ React, Vue ฯลฯ ซึ่งทำงานในเบราว์เซอร์และรับหน้าที่เกี่ยวกับการโต้ตอบของผู้ใช้
- สามารถเรนเดอร์ Client Island ภายใน Astro Component ได้ แต่ไม่สามารถเรียก Astro Component จากฝั่ง Client Island ได้
- โครงสร้างนี้รับประกัน การไหลทางเดียว ของข้อมูล ว่าจะไหลจากเซิร์ฟเวอร์ไปยังไคลเอนต์เท่านั้นเสมอ
ตัวอย่างโค้ดและการแบ่งบทบาท
- ในโค้ดตัวอย่าง
PostPreview.astroจะ อ่านไฟล์ จากฝั่งเซิร์ฟเวอร์แล้วดึงชื่อเรื่องออกมา ก่อนส่งข้อมูลดังกล่าวต่อให้ Client Island - LikeButton เขียนด้วย React และหลังจากเบราว์เซอร์โหลดแล้วจะรับผิดชอบ การเปลี่ยนสถานะ และอีเวนต์คลิกของผู้ใช้
- Astro Component และ Client Island ทำงานอยู่ใน คนละโลก และการส่งข้อมูลก็จะไหลลงจาก Astro Component เท่านั้น
เปรียบเทียบกับ React Server Components(RSC)
- ใน RSC ก็มีการแยกเป็น Server Component และ Client Component คล้ายกับ Astro
- ใน React Server Component จะประกาศเซิร์ฟเวอร์คอมโพเนนต์ด้วยฟังก์ชัน JavaScript และระบุอย่างชัดเจนว่าจุดใดคือจุดเริ่มของโค้ดฝั่งไคลเอนต์ด้วยคำสั่ง 'use client'
- ใน RSC ไฟล์คอมโพเนนต์เดียวกันสามารถทำหน้าที่ได้ทั้งฝั่งเซิร์ฟเวอร์และไคลเอนต์ โดยไม่ต้องแยกด้วยนามสกุลไฟล์หรือโครงสร้างเฉพาะแบบ Astro และสามารถย้ายขอบเขตได้ตามต้องการด้วยการประกาศ
'use client' - หากคอมโพเนนต์ใช้ฟีเจอร์เฉพาะฝั่งไคลเอนต์ (เช่น useState) หรือฟีเจอร์เฉพาะฝั่งเซิร์ฟเวอร์ (เช่น การเข้าถึง DB) แล้วนำไปใช้ในสภาพแวดล้อมที่ไม่ถูกต้อง จะเกิด build error เพื่อให้ได้ฟีดแบ็กที่ชัดเจน
ความต่างด้านภาพรวมและโครงสร้างระหว่าง Astro กับ RSC
- Astro มี ขอบเขตที่ชัดเจน จากการแยกไฟล์
.astroและไฟล์ JS/TS - RSC นั้นทุกอย่างเป็น React โดยพื้นฐาน จึงมี ความสามารถในการแชร์โค้ดและความยืดหยุ่น สูงกว่ามาก
- ตัวอย่างเช่น คอมโพเนนต์แบบเป็นกลาง ที่ไม่ใช้ state หรือความสามารถฝั่งเซิร์ฟเวอร์ (เช่น Markdown parser) สามารถใช้ได้ทั้งสองฝั่ง
- ใน RSC จะตัดสินโดยอัตโนมัติว่าคอมโพเนนต์นั้นทำงานอยู่ในโลกใดตามเส้นทางการ import
ข้อดีและข้อจำกัดของโมเดล RSC
- จุดเด่นของ RSC คือ การนำโค้ดกลับมาใช้ซ้ำและความยืดหยุ่นในการย้ายบทบาท
- คอมโพเนนต์ใด ๆ ก็สามารถย้ายขอบเขตได้ง่ายตามต้องการ เพียงประกาศ
'use client' - ใน Astro หากลักษณะของ UI เปลี่ยนจาก static เป็น dynamic หรือกลับกัน การแปลงโค้ดอาจยุ่งยาก แต่ RSC ช่วยแก้เรื่องนี้ได้อย่างง่ายดาย
- คอมโพเนนต์ใด ๆ ก็สามารถย้ายขอบเขตได้ง่ายตามต้องการ เพียงประกาศ
- ข้อเสียของ RSC คือ เรียนรู้ได้ยากกว่า
- นักพัฒนาต้องคอยคิดอยู่เสมอว่าตอนนี้ตนเองอยู่ใน “โลกไหน” แต่หากพลาดก็จะได้รับฟีดแบ็กอย่างรวดเร็วผ่าน build error
- ใน Astro ยิ่งส่วนของ UI ที่เป็น dynamic มีมากขึ้น โครงสร้างก็ยิ่งซับซ้อนขึ้น ขณะที่ RSC มี React tree ที่รวมเป็นหนึ่งเดียวทั้งต้น ทำให้เรื่อง state และการส่งต่อ context (Context) เป็นไปอย่างเป็นธรรมชาติ
Astro ที่ยึด HTML เป็นศูนย์กลาง กับ RSC ที่ยึด React tree เป็นศูนย์กลาง
- ผลลัพธ์ของ Astro คือ HTML โดยเมื่อมีการย้ายหน้า ระบบจะรีเฟรชทั้งหน้า และไม่ได้มอบประสบการณ์แบบ SPA อย่างสมบูรณ์
- ผลลัพธ์ของ RSC คือ React tree (เริ่มต้นเป็น HTML และระหว่างการนำทางจะส่งเป็น JSON เป็นต้น)
- ด้วยเหตุนี้จึง ผสานข้อดีของ SPA และ MPA เข้าด้วยกัน ได้
- สามารถทำ partial refresh โดยอัปเดตเฉพาะบางส่วนของ UI จากฝั่งเซิร์ฟเวอร์โดยตรง จึงรับข้อมูลแบบ dynamic และคงสถานะฝั่งไคลเอนต์ไว้ได้ง่าย
รองรับความสามารถขั้นสูงของ React
- ด้วยโครงสร้าง tree แบบ ผสมระหว่างเซิร์ฟเวอร์-ไคลเอนต์ จึงรองรับความสามารถขั้นสูงของ React (เช่น
<Suspense>, view transitions ฯลฯ) ได้อย่างเป็นธรรมชาติ - ยังจัดการสถานะการโหลดที่ declarative จากฝั่งไคลเอนต์ รวมถึงการหน่วงการโหลดของฟอนต์/รูปภาพ/JavaScript/style ได้ด้วย
- ทุกความสามารถของ React ทำงานแบบ end-to-end ได้โดยไม่ติดข้อจำกัดของขอบเขตระหว่างเซิร์ฟเวอร์กับไคลเอนต์
สถานะของ RSC และ Astro
- Astro คือ เฟรมเวิร์กที่สมบูรณ์ ขณะที่ RSC ใกล้เคียงกับ building block หรือ มาตรฐาน ของเฟรมเวิร์กมากกว่า
- อิมพลีเมนเทชัน RSC อย่างเป็นทางการมี Next.js App Router และ Parcel RSC
บทสรุปและคำแนะนำ
- ประสบการณ์นักพัฒนา (DX) ของ RSC ยังมีความขรุขระอยู่บ้าง แต่ก็คุ้มค่าที่จะเรียนรู้
- หากยังไม่เคยลอง Astro ก็แนะนำให้ลอง และสำหรับนักพัฒนาที่รู้สึกว่า RSC ยาก Astro อาจเป็นทางเข้าที่นุ่มนวลกว่า
- แม้แต่สำหรับนักพัฒนาที่เคยใช้แต่ React ฝั่งไคลเอนต์ Astro ก็อาจมอบประสบการณ์การแก้ปัญหาที่คาดไม่ถึงได้
3 ความคิดเห็น
ตอนนี้กำลังรีแฟกเตอร์แอป React รุ่นเก่าไปเป็น Astro อยู่
ในบทความเน้นย้ำเรื่อง "บริบทที่ผสานรวมกัน" โดยต้องเข้าใจว่าแม้ "บริบทที่ผสานรวมกัน" จะช่วยให้สร้างบริการได้รวดเร็ว แต่สักวันหนึ่งมันอาจกลายเป็นหนี้ทางเทคนิคได้
ในมุมมองของการบำรุงรักษาระยะยาวของบริการ "การเชื่อมโยงกันอย่างแน่นหนาแบบรวมศูนย์" ย่อมสู้ "การเชื่อมโยงแบบหลวม ๆ ของโมดูลอิสระ" ไม่ได้
และ Astro ก็คือเฟรมเวิร์กที่ยืดหยุ่นที่สุดสำหรับสิ่งนี้
Astro : เผยแพร่ JavaScript ให้น้อยที่สุด
Astro 3.0 เปิดตัว
ความคิดเห็นบน Hacker News