Photo by Lautaro Andreani on Unsplash
สวัสดีทุกคน! วันหยุดยาววันแรกเป็นอย่างไรบ้าง? วันนี้ผมอยากจะแบ่งปันแนวคิดเกี่ยวกับโหมดการเรนเดอร์เว็บแบบต่างๆ ให้ฟังกันครับ ได้แก่ SSG, SSR, CSR, และ ISR หน้าตาอาจจะดูคล้ายๆ กัน แต่รายละเอียดนั้นแตกต่างกัน ก่อนจะตัดสินใจว่าจะใช้อันไหน เรามาดูคำแนะนำด้านล่างกันก่อนดีกว่า!
Static Site Generation (SSG)
SSG หรือการสร้างเว็บไซต์แบบสถิต (Static Generation) หมายถึงการสร้างไฟล์ HTML เมื่อทำการ build โปรเจกต์ทั้งหมด ไฟล์ HTML เหล่านี้มีข้อมูลที่จำเป็นต้องแสดงอยู่แล้ว โหมดการเรนเดอร์นี้เป็นประเภทหนึ่งของ pre-rendering SSG เหมาะอย่างยิ่งสำหรับเว็บไซต์สถิตที่เนื้อหาไม่มีการเปลี่ยนแปลง เพราะข้อมูลทั้งหมดได้มาตอน build ไฟล์ HTML เหล่านี้สามารถวางไว้บน CDN และแคช (cache) เพื่อปรับปรุงประสิทธิภาพของเว็บไซต์ นอกจากนี้ การใช้โหมดการเรนเดอร์แบบ SSG ยังเป็นประโยชน์ต่อ SEO อีกด้วย
Server-side Rendering (SSR)
SSR หรือการเรนเดอร์ฝั่งเซิร์ฟเวอร์ (Server-side Rendering) หมายความว่าทุกครั้งที่เบราว์เซอร์ (ฝั่งไคลเอนต์) ส่งคำขอ (request) ไป เซิร์ฟเวอร์จะสร้างไฟล์ HTML และส่งกลับไปยังเบราว์เซอร์เพื่อแสดงผล โหมดการเรนเดอร์นี้เหมาะอย่างยิ่งสำหรับข้อมูลที่มีการเปลี่ยนแปลงบ่อยครั้ง อย่างไรก็ตาม เนื่องจากเซิร์ฟเวอร์ต้องใช้เวลาในการสร้างไฟล์ HTML เวลาในการตอบสนองของเว็บไซต์จึงอาจนานขึ้น และผู้ใช้จะเห็นหน้าจอสีขาวขณะรอ SSR ก็ถือเป็น pre-rendering ประเภทหนึ่งเช่นกัน ดังนั้นจึงค่อนข้างเป็นมิตรกับ SEO~ แต่ควรทราบว่าวิธีนี้ต้องการให้เซิร์ฟเวอร์ประมวลผลคำขอของผู้ใช้อย่างต่อเนื่อง
Client-side Rendering (CSR)
CSR หรือการเรนเดอร์ฝั่งไคลเอนต์ (Client-side Rendering) ความหมายก็ตรงตามชื่อเลยครับ ไฟล์ HTML ที่เซิร์ฟเวอร์ส่งไปยังเบราว์เซอร์แทบจะเรียกได้ว่าไม่มีเนื้อหา เบราว์เซอร์จะสามารถเรนเดอร์บนหน้าจอได้ก็ต่อเมื่อดึงข้อมูลจากเซิร์ฟเวอร์เสร็จแล้ว โหมดการเรนเดอร์ที่ใช้โดย SPA (Single Page Application เช่น React หรือ Vue) ก็คือ CSR ข้อได้เปรียบที่ใหญ่ที่สุดของโหมดนี้คือไม่จำเป็นต้องดึงไฟล์จากเซิร์ฟเวอร์อีกครั้งเมื่อเปลี่ยนหน้า ดังนั้นผู้ใช้จะไม่เห็นหน้าจอสีขาว ซึ่งถือว่าเป็นประสบการณ์ผู้ใช้ที่ดีมาก อย่างไรก็ตาม เวลาในการเรนเดอร์จะขึ้นอยู่กับสภาพแวดล้อมของไคลเอนต์ และด้วยเหตุนี้ ภาระของเซิร์ฟเวอร์จึงลดลงไปได้มาก
Incremental Static Regeneration (ISR)
ISR หรือการสร้างสถิตแบบเพิ่มหน่วย (Incremental Static Regeneration) เป็นโหมดการเรนเดอร์ที่ได้ยินกันน้อยกว่า และถือเป็น pre-rendering ประเภทหนึ่งเช่นกัน ISR จะสร้างไฟล์ HTML ทั้งหมด (หรือบางส่วน) เมื่อทำการ build โปรเจกต์ เมื่อมีคำขอใหม่และผ่านเวลาที่กำหนดไว้แล้ว เซิร์ฟเวอร์จะให้ไฟล์เก่าแก่เบราว์เซอร์ก่อน ในขณะเดียวกันก็จะสร้างไฟล์ล่าสุดใหม่ในเบื้องหลัง แล้วค่อยส่งไปยังเบราว์เซอร์เพื่อแสดงผลหลังจากสร้างเสร็จ หากผู้ใช้เข้าไปยังหน้าที่ยังไม่ได้ถูก generate (สร้าง) เซิร์ฟเวอร์จะสร้างไฟล์นั้นทันทีและทำการ cache ไว้ เพื่อให้ผู้ใช้คนต่อไปที่เข้ามาหน้านี้สามารถดึงไฟล์จาก cache ได้โดยตรง ISR คล้ายกับ SSG มาก แต่แก้ปัญหาที่ SSG ไม่สามารถอัปเดตเนื้อหาข้อมูลได้ และไฟล์ HTML ก็จะถูก cache ไว้บน CDN ด้วย ดังนั้นจึงช่วยลดภาระของเซิร์ฟเวอร์เมื่อเทียบกับ SSR
แล้วควรใช้อันไหนดี?
โหมดการเรนเดอร์แต่ละแบบมีข้อดีและข้อเสีย และการเลือกใช้อันไหนก็ขึ้นอยู่กับโปรเจกต์ของเรา ไม่มีผู้ชนะที่ชัดเจนครับ
- แดชบอร์ดระบบภายในที่ข้อมูลมีการเปลี่ยนแปลงตลอดเวลาและไม่ต้องการ SEO เหมาะมากที่จะใช้ CSR
- หากอัตราการเปลี่ยนแปลงข้อมูลไม่ต่ำแต่ต้องการ SEO คุณอาจพิจารณาใช้ SSR
- หากข้อมูลแทบไม่ต้องอัปเดตเลย เช่น เว็บไซต์กิจกรรมหรือการตลาด และ SEO ก็สำคัญ การใช้ SSG นั้นเหมาะสมมาก
- หากข้อมูลไม่ค่อยจำเป็นต้องอัปเดตหรือมีหน้าเพจมากเกินไปและต้องการ SEO เช่น หน้าสินค้า งั้น ISR ก็เป็นตัวเลือกที่ดีครับ
ผมได้วาดตารางมาด้วย (แต่เป็นภาษาอังกฤษนะ XD) ลองดูกันได้ครับ~

Pre-render ใน Next.js
Next.js มีการรองรับโหมดการเรนเดอร์ที่กล่าวถึงข้างต้นในตัว และยังตั้งค่าเริ่มต้นให้ใช้ SSG ในการเรนเดอร์หน้าเว็บที่ไม่จำเป็นต้องดึงข้อมูล (fetch) หากคุณต้องการดึงข้อมูลจากเซิร์ฟเวอร์ มันจะถูกใช้ผสมกับ CSR (hybrid) หากคุณต้องการใช้โหมดการเรนเดอร์อื่นๆ คุณสามารถใช้ฟังก์ชันต่อไปนี้ที่ Next.js จัดเตรียมไว้ให้:
| Function | Description |
|---|---|
| getStaticProps (Static Generation) | ดึงข้อมูลที่จำเป็นตอน build และใส่ลงในไฟล์ HTML |
| getStaticPaths (Static Generation) | ตัดสินใจว่า dynamic routes ไหนบ้างที่ต้องถูกสร้างเป็นไฟล์ HTML ตอน build |
| getServerSideProps (Server-side Rendering) | ฟังก์ชันที่จะทำงานทุกครั้งที่เบราว์เซอร์ส่งคำขอเพื่อดึงข้อมูลที่จำเป็น |
สรุป
วันนี้พอแค่นี้ก่อน พรุ่งนี้มาต่อกันนะครับ~ พรุ่งนี้ผมจะมาแชร์วิธีใช้ฟังก์ชันทั้งสามนั้นเพื่อสร้างเว็บไซต์ด้วยโหมดการเรนเดอร์ที่แตกต่างกัน! ทุกคนมีความคิดเห็นอย่างไรเกี่ยวกับโหมดการเรนเดอร์ที่ได้เรียนรู้ในวันนี้บ้างครับ?