การแสดงผลบนเว็บ

เผยแพร่เมื่อวันที่ 6 กุมภาพันธ์ 2019 อัปเดตล่าสุดเมื่อวันที่ 5 มกราคม 2026

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

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

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

คำศัพท์

ก่อนอื่น เราจะอธิบายคำศัพท์บางคำที่เราจะใช้

การแสดงผล

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

ประสิทธิภาพ

เวลาที่ได้รับข้อมูลไบต์แรก (TTFB)
ระยะเวลาระหว่างการคลิกลิงก์และการโหลดเนื้อหาไบต์แรกในหน้าใหม่
First Contentful Paint (FCP)
เวลาที่เนื้อหาที่ขอ (เนื้อหาบทความ ฯลฯ) ปรากฏขึ้น
Interaction to Next Paint (INP)
เมตริกตัวแทนที่ประเมินว่าหน้าเว็บตอบสนองต่ออินพุตของผู้ใช้อย่างรวดเร็วและสม่ำเสมอหรือไม่
เวลาทั้งหมดในการบล็อก (TBT)
เมตริกพร็อกซีสำหรับ INP ที่คำนวณระยะเวลาที่เทรดหลักถูกบล็อกระหว่างการโหลดหน้าเว็บ

การแสดงผลฝั่งเซิร์ฟเวอร์

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

โดยทั่วไปแล้ว การแสดงผลฝั่งเซิร์ฟเวอร์จะทำให้ FCP รวดเร็ว การเรียกใช้ตรรกะของหน้าและการแสดงผลบนเซิร์ฟเวอร์ช่วยให้คุณไม่ต้องส่ง JavaScript จำนวนมากไปยังไคลเอ็นต์ ซึ่งจะช่วยลด TBT ของหน้าเว็บ และยังอาจทำให้ INP ต่ำลงด้วย เนื่องจากเทรดหลักจะไม่ถูกบล็อกบ่อยนักในระหว่างการโหลดหน้าเว็บ เมื่อเทรดหลักถูกบล็อกน้อยลง การโต้ตอบของผู้ใช้ก็มีโอกาสทำงานได้เร็วขึ้น

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

แผนภาพแสดงการแสดงผลฝั่งเซิร์ฟเวอร์และการเรียกใช้ JavaScript ที่ส่งผลต่อ FCP และ TTI
FCP และ TTI ที่มีการแสดงผลฝั่งเซิร์ฟเวอร์

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

การแสดงผลฝั่งเซิร์ฟเวอร์เพียงพอสำหรับแอปพลิเคชันของคุณหรือไม่นั้นขึ้นอยู่กับประเภทประสบการณ์ที่คุณกำลังสร้างเป็นส่วนใหญ่ มีการถกเถียงกันมานานแล้วว่าการแสดงผลฝั่งเซิร์ฟเวอร์กับการแสดงผลฝั่งไคลเอ็นต์แบบใดเหมาะสมกว่ากัน แต่คุณเลือกใช้การแสดงผลฝั่งเซิร์ฟเวอร์สำหรับบางหน้าและไม่ใช้สำหรับหน้าอื่นๆ ได้เสมอ บางเว็บไซต์ใช้เทคนิคการแสดงผลแบบผสมผสานและประสบความสำเร็จ ตัวอย่างเช่น Netflix แสดงผลหน้า Landing Page ที่ค่อนข้างคงที่ฝั่งเซิร์ฟเวอร์ ขณะที่prefetching JavaScript สำหรับหน้าเว็บที่มีการโต้ตอบสูง ซึ่งทำให้หน้าเว็บที่แสดงผลฝั่งไคลเอ็นต์ที่หนักกว่าเหล่านี้มีโอกาสโหลดได้เร็วขึ้น

เฟรมเวิร์ก ไลบรารี และสถาปัตยกรรมสมัยใหม่จำนวนมากช่วยให้คุณแสดงผลแอปพลิเคชันเดียวกันได้ทั้งในฝั่งไคลเอ็นต์และเซิร์ฟเวอร์ คุณสามารถใช้เทคนิคเหล่านี้สำหรับการแสดงผลฝั่งเซิร์ฟเวอร์ อย่างไรก็ตาม สถาปัตยกรรมที่การแสดงผลเกิดขึ้นทั้งบนเซิร์ฟเวอร์และไคลเอ็นต์เป็นโซลูชันประเภทหนึ่งที่มีลักษณะเฉพาะด้านประสิทธิภาพและข้อดีข้อเสียที่แตกต่างกันมาก ผู้ใช้ React สามารถใช้ DOM API ของเซิร์ฟเวอร์หรือโซลูชันที่สร้างขึ้นจาก API ดังกล่าว เช่น Next.js สำหรับการแสดงผลฝั่งเซิร์ฟเวอร์ ผู้ใช้ Vue สามารถใช้คู่มือการแสดงผลฝั่งเซิร์ฟเวอร์ของ Vue หรือ Nuxt Angular มี Universal

อย่างไรก็ตาม โซลูชันยอดนิยมส่วนใหญ่ใช้การเติมข้อมูลบางรูปแบบ ดังนั้นโปรดระวังแนวทางที่เครื่องมือของคุณใช้

การแสดงผลแบบคงที่

การแสดงผลแบบคงที่จะเกิดขึ้นในเวลาบิลด์ วิธีนี้ช่วยให้ FCP รวดเร็ว รวมถึง TBT และ INP ต่ำลง ตราบใดที่คุณจำกัดปริมาณ JavaScript ฝั่งไคลเอ็นต์ในหน้าเว็บ นอกจากนี้ยังทำให้ TTFB ทำงานได้อย่างรวดเร็วและสม่ำเสมอ ซึ่งแตกต่างจากการแสดงผลฝั่งเซิร์ฟเวอร์ เนื่องจากไม่จำเป็นต้องสร้าง HTML สำหรับหน้าเว็บแบบไดนามิกบนเซิร์ฟเวอร์ โดยทั่วไปแล้ว การแสดงผลแบบคงที่หมายถึงการสร้างไฟล์ HTML แยกต่างหากสำหรับแต่ละ URL ล่วงหน้า เมื่อสร้างการตอบกลับ HTML ไว้ล่วงหน้า คุณจะติดตั้งใช้งานการแสดงผลแบบคงที่ใน CDN หลายรายการเพื่อใช้ประโยชน์จากการแคชไปยังเซิร์ฟเวอร์ปลายทางได้

แผนภาพแสดงการแสดงผลแบบคงที่และการเรียกใช้ JavaScript (ไม่บังคับ) ที่ส่งผลต่อ FCP และ TTI
FCP และ TTI ที่มีการแสดงผลแบบคงที่

โซลูชันสำหรับการแสดงผลแบบคงที่มีหลากหลายรูปแบบและขนาด เครื่องมืออย่าง Gatsby ได้รับการออกแบบมาเพื่อให้นักพัฒนาแอปเห็นว่าแอปพลิเคชันของตนแสดงผลแบบไดนามิก ไม่ใช่สร้างขึ้นเป็นขั้นตอนการบิลด์ เครื่องมือสร้างเว็บไซต์แบบคงที่ เช่น 11ty, Jekyll และ Metalsmith จะใช้ลักษณะแบบคงที่ ซึ่งให้แนวทางที่อิงตามเทมเพลตมากกว่า

ข้อเสียอย่างหนึ่งของการแสดงผลแบบคงที่คือต้องสร้างไฟล์ HTML แต่ละไฟล์สำหรับ URL ที่เป็นไปได้ทั้งหมด ซึ่งอาจเป็นเรื่องยากหรือเป็นไปไม่ได้เลยเมื่อคุณต้องคาดการณ์ URL เหล่านั้นล่วงหน้าและสำหรับเว็บไซต์ที่มีหน้าเว็บที่ไม่ซ้ำกันจำนวนมาก

ผู้ใช้ React อาจคุ้นเคยกับ Gatsby, Next.js static export หรือ Navi ซึ่งทั้งหมดนี้ช่วยให้สร้างหน้าเว็บจากคอมโพเนนต์ได้สะดวก อย่างไรก็ตาม การแสดงผลแบบคงที่และการแสดงผลล่วงหน้ามีลักษณะการทำงานที่แตกต่างกัน กล่าวคือ หน้าเว็บที่แสดงผลแบบคงที่จะมีการโต้ตอบโดยไม่ต้องเรียกใช้ JavaScript ฝั่งไคลเอ็นต์มากนัก ในขณะที่การแสดงผลล่วงหน้าจะปรับปรุง FCP ของแอปพลิเคชันหน้าเว็บเดียวที่ต้องเปิดเครื่องในฝั่งไคลเอ็นต์เพื่อให้หน้าเว็บมีการโต้ตอบอย่างแท้จริง

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

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

การแสดงผลฝั่งเซิร์ฟเวอร์เทียบกับการแสดงผลแบบคงที่

การแสดงผลฝั่งเซิร์ฟเวอร์ไม่ใช่โซลูชันที่ดีที่สุดสําหรับทุกอย่าง เนื่องจากลักษณะแบบไดนามิกอาจมีค่าใช้จ่ายในการประมวลผลสูง โซลูชันการแสดงผลฝั่งเซิร์ฟเวอร์จำนวนมากไม่ล้างข้อมูลตั้งแต่เนิ่นๆ ทำให้ TTFB ล่าช้า หรือเพิ่มข้อมูลที่ส่งเป็น 2 เท่า (เช่น สถานะในบรรทัดที่ JavaScript ใช้ในไคลเอ็นต์) ใน React renderToString() อาจทำงานช้าเนื่องจากเป็นแบบซิงโครนัสและเทรดเดียว React Server DOM API ที่ใหม่กว่ารองรับการสตรีม ซึ่งจะช่วยให้ส่วนแรกของการตอบกลับ HTML ไปยังเบราว์เซอร์ได้เร็วขึ้นขณะที่ส่วนที่เหลือยังคงสร้างอยู่ในเซิร์ฟเวอร์

การแสดงผลฝั่งเซิร์ฟเวอร์ "ที่ถูกต้อง" อาจเกี่ยวข้องกับการค้นหาหรือสร้างโซลูชันสำหรับการแคชคอมโพเนนต์ การจัดการการใช้หน่วยความจำ การใช้เทคนิค Memoization และข้อกังวลอื่นๆ คุณมักจะประมวลผลหรือสร้างแอปเดียวกันซ้ำ 2 ครั้ง โดยครั้งแรกในฝั่งไคลเอ็นต์และครั้งที่ 2 ในฝั่งเซิร์ฟเวอร์ การแสดงผลฝั่งเซิร์ฟเวอร์ที่แสดงเนื้อหาเร็วขึ้นไม่ได้หมายความว่าคุณจะมีงานน้อยลง หากคุณมีงานจำนวนมากในฝั่งไคลเอ็นต์หลังจากที่การตอบกลับ HTML ที่เซิร์ฟเวอร์สร้างขึ้นมาถึงฝั่งไคลเอ็นต์แล้ว ก็อาจยังทำให้ TBT และ INP ของเว็บไซต์สูงขึ้นได้

การแสดงผลฝั่งเซิร์ฟเวอร์จะสร้าง HTML ตามคำขอสำหรับแต่ละ URL แต่อาจช้ากว่าการแสดงเนื้อหาที่แสดงผลแบบคงที่ หากคุณสามารถทำงานเพิ่มเติมได้ การแสดงผลฝั่งเซิร์ฟเวอร์รวมถึงการแคช HTML จะช่วยลดเวลาในการแสดงผลของเซิร์ฟเวอร์ได้อย่างมาก ข้อดีของการแสดงผลฝั่งเซิร์ฟเวอร์คือความสามารถในการดึงข้อมูล "แบบเรียลไทม์" ได้มากขึ้น และตอบสนองต่อชุดคำขอที่สมบูรณ์กว่าการแสดงผลแบบคงที่ หน้าเว็บที่ต้องมีการปรับเปลี่ยนในแบบของคุณเป็นตัวอย่างที่ชัดเจนของประเภทคำขอที่ทำงานได้ไม่ดีกับการแสดงผลแบบคงที่

การแสดงผลฝั่งเซิร์ฟเวอร์ยังช่วยให้คุณตัดสินใจได้อย่างน่าสนใจเมื่อสร้าง PWA ฉันควรใช้การแคชเซอร์วิสเวิร์กเกอร์แบบเต็มหน้า หรือแสดงผลเนื้อหาแต่ละส่วนบนเซิร์ฟเวอร์ดี

การแสดงผลฝั่งไคลเอ็นต์

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

การแสดงผลฝั่งไคลเอ็นต์อาจสร้างและทำให้ทำงานได้อย่างรวดเร็วบนอุปกรณ์เคลื่อนที่ได้ยาก การทำงานเพียงเล็กน้อยเพื่อรักษางบประมาณ JavaScript ที่จำกัดและส่งมอบคุณค่าโดยใช้การไปกลับให้น้อยที่สุดจะช่วยให้คุณได้รับการแสดงผลฝั่งไคลเอ็นต์ที่เกือบจะจำลองประสิทธิภาพของการแสดงผลฝั่งเซิร์ฟเวอร์ล้วนๆ คุณสามารถทำให้โปรแกรมแยกวิเคราะห์ทำงานได้เร็วขึ้นโดยการส่งสคริปต์และข้อมูลที่สำคัญโดยใช้ <link rel=preload> นอกจากนี้ เราขอแนะนำให้พิจารณาใช้รูปแบบต่างๆ เช่น PRPL เพื่อให้การนำทางครั้งแรกและครั้งต่อๆ ไปดูรวดเร็วทันใจ

แผนภาพแสดงการแสดงผลฝั่งไคลเอ็นต์ที่ส่งผลต่อ FCP และ TTI
FCP และ TTI ที่มีการแสดงผลฝั่งไคลเอ็นต์

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

ประสบการณ์ที่ใช้การแสดงผลฝั่งไคลเอ็นต์และอาศัยแพ็กเกจ JavaScript ขนาดใหญ่ควรพิจารณาการแยกโค้ดอย่างเข้มงวดเพื่อลด TBT และ INP ระหว่างการโหลดหน้าเว็บ รวมถึงการโหลด JavaScript แบบ Lazy Loading เพื่อแสดงเฉพาะสิ่งที่ผู้ใช้ต้องการเมื่อจำเป็น สำหรับประสบการณ์ที่มีการโต้ตอบเพียงเล็กน้อยหรือไม่มีเลย การแสดงผลฝั่งเซิร์ฟเวอร์อาจเป็นโซลูชันที่ปรับขนาดได้มากกว่าสำหรับปัญหาเหล่านี้

สำหรับผู้ที่สร้างแอปพลิเคชันหน้าเว็บเดียว การระบุส่วนหลักของอินเทอร์เฟซผู้ใช้ที่หน้าเว็บส่วนใหญ่ใช้ร่วมกันจะช่วยให้คุณใช้เทคนิคการแคช Application Shell ได้ เมื่อใช้ร่วมกับ Service Worker วิธีนี้จะช่วยปรับปรุงประสิทธิภาพที่รับรู้ได้ในการเข้าชมซ้ำอย่างมาก เนื่องจากหน้าเว็บสามารถโหลด HTML ของ Application Shell และทรัพยากร Dependency จาก CacheStorage ได้อย่างรวดเร็ว

การคืนสภาพจะรวมการแสดงผลฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์เข้าด้วยกัน

Hydration เป็นแนวทางที่ลดข้อดีข้อเสียระหว่างการแสดงผลฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ด้วยการทำทั้ง 2 อย่าง คำขอการนำทาง เช่น การโหลดหน้าเว็บแบบเต็มหรือการโหลดซ้ำ จะได้รับการจัดการโดยเซิร์ฟเวอร์ที่แสดงผลแอปพลิเคชันเป็น HTML จากนั้น JavaScript และข้อมูลที่ใช้สำหรับการแสดงผลจะฝังอยู่ในเอกสารผลลัพธ์ เมื่อดำเนินการอย่างระมัดระวัง วิธีนี้จะทำให้ได้ FCP ที่รวดเร็วเหมือนกับการแสดงผลฝั่งเซิร์ฟเวอร์ จากนั้นจึง "รับช่วงต่อ" โดยแสดงผลอีกครั้งในฝั่งไคลเอ็นต์

วิธีนี้เป็นโซลูชันที่มีประสิทธิภาพ แต่อาจมีข้อเสียด้านประสิทธิภาพที่สำคัญ

ข้อเสียหลักของการแสดงผลฝั่งเซิร์ฟเวอร์ที่มีการรีไฮเดรตคืออาจส่งผลเสียอย่างมากต่อ TBT และ INP แม้ว่าจะปรับปรุง FCP ก็ตาม หน้าเว็บที่แสดงผลฝั่งเซิร์ฟเวอร์อาจดูเหมือนโหลดและโต้ตอบได้ แต่ไม่สามารถตอบสนองต่ออินพุตได้จริงจนกว่าสคริปต์ฝั่งไคลเอ็นต์สำหรับคอมโพเนนต์จะทำงานและมีการแนบเครื่องจัดการเหตุการณ์ ซึ่งอาจใช้เวลาหลายนาทีบนอุปกรณ์เคลื่อนที่ ทำให้ผู้ใช้สับสนและหงุดหงิด

ปัญหาการเติมน้ำ: แอปเดียวในราคา 2 แอป

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

เอกสาร HTML ที่มี UI แบบอนุกรม ข้อมูลในบรรทัด และสคริปต์ bundle.js

เซิร์ฟเวอร์จะแสดงคำอธิบาย UI ของแอปพลิเคชันเพื่อตอบสนองต่อคำขอการนำทาง แต่ยังแสดงข้อมูลแหล่งที่มาที่ใช้ในการเขียน UI นั้น และสำเนาที่สมบูรณ์ของการติดตั้งใช้งาน UI ซึ่งจะเปิดขึ้นในไคลเอ็นต์ด้วย UI จะไม่โต้ตอบจนกว่า bundle.js จะโหลดและดำเนินการเสร็จสิ้น

เมตริกประสิทธิภาพที่รวบรวมจากเว็บไซต์จริงที่ใช้การแสดงผลฝั่งเซิร์ฟเวอร์และการเติมน้ำบ่งชี้ว่าวิธีนี้แทบจะไม่ใช่ตัวเลือกที่ดีที่สุด เหตุผลที่สำคัญที่สุดคือผลกระทบต่อประสบการณ์ของผู้ใช้ เมื่อหน้าเว็บดูเหมือนพร้อมใช้งาน แต่ฟีเจอร์แบบอินเทอร์แอกทีฟกลับไม่ทำงาน

ผลเสียของการแสดงผลฝั่งไคลเอ็นต์ใน TTI

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

สตรีมการแสดงผลฝั่งเซิร์ฟเวอร์และรีไฮเดรตแบบต่อเนื่อง

การแสดงผลฝั่งเซิร์ฟเวอร์มีการพัฒนาหลายอย่างในช่วง 2-3 ปีที่ผ่านมา

การแสดงผลฝั่งเซิร์ฟเวอร์แบบสตรีมมิงช่วยให้คุณส่ง HTML เป็นกลุ่มๆ ที่เบราว์เซอร์สามารถแสดงผลแบบค่อยเป็นค่อยไปเมื่อได้รับ ซึ่งจะช่วยให้มาร์กอัปเข้าถึงผู้ใช้ได้เร็วขึ้น และทำให้ FCP เร็วขึ้น ใน React สตรีมที่เป็นแบบอะซิงโครนัสใน renderToPipeableStream() เมื่อเทียบกับแบบซิงโครนัส renderToString() หมายความว่าระบบจะจัดการแรงดันย้อนกลับได้ดี

Progressive rehydration ก็เป็นสิ่งที่ควรพิจารณาเช่นกัน (React ได้นำไปใช้แล้ว) ด้วยวิธีนี้ ส่วนต่างๆ ของแอปพลิเคชันที่แสดงผลฝั่งเซิร์ฟเวอร์จะ "บูต" เมื่อเวลาผ่านไป แทนที่จะใช้วิธีการทั่วไปในปัจจุบันในการเริ่มต้นแอปพลิเคชันทั้งหมดพร้อมกัน วิธีนี้จะช่วยลดปริมาณ JavaScript ที่จำเป็นในการทำให้หน้าเว็บมีการโต้ตอบ เนื่องจากช่วยให้คุณเลื่อนการอัปเกรดฝั่งไคลเอ็นต์ของส่วนที่มีลำดับความสำคัญต่ำของหน้าเว็บเพื่อป้องกันไม่ให้บล็อกเทรดหลัก ซึ่งจะช่วยให้การโต้ตอบของผู้ใช้เกิดขึ้นเร็วขึ้นหลังจากที่ผู้ใช้เริ่มการโต้ตอบ

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

การเติมน้ำบางส่วน

การเติมน้ำบางส่วนเป็นสิ่งที่ทำได้ยาก แนวทางนี้เป็นส่วนขยายของ Progressive Rehydration ที่วิเคราะห์แต่ละส่วนของหน้า (คอมโพเนนต์ มุมมอง หรือต้นไม้) และระบุส่วนที่มีการโต้ตอบน้อยหรือไม่มีการโต้ตอบ สำหรับส่วนที่คงที่ส่วนใหญ่เหล่านี้ โค้ด JavaScript ที่เกี่ยวข้องจะเปลี่ยนเป็นข้อมูลอ้างอิงแบบเฉื่อยและฟีเจอร์ตกแต่ง ซึ่งจะลดรอยเท้าฝั่งไคลเอ็นต์ให้เหลือเกือบเป็นศูนย์

แนวทางการคืนสภาพบางส่วนมาพร้อมกับปัญหาและการประนีประนอมของตัวเอง ซึ่งทำให้เกิดความท้าทายที่น่าสนใจสำหรับการแคช และการนำทางฝั่งไคลเอ็นต์หมายความว่าเราไม่สามารถสันนิษฐานได้ว่า HTML ที่แสดงผลฝั่งเซิร์ฟเวอร์สำหรับส่วนที่ไม่มีการโต้ตอบของแอปพลิเคชันจะพร้อมใช้งานโดยไม่ต้องโหลดหน้าเว็บแบบเต็ม

การแสดงผลแบบ Trisomorphic

หากคุณใช้ Service Worker ได้ ให้พิจารณาการแสดงผลแบบ Trisomorphic เทคนิคนี้ช่วยให้คุณใช้การแสดงผลฝั่งเซิร์ฟเวอร์แบบสตรีมมิงสำหรับการนำทางเริ่มต้นหรือการนำทางที่ไม่ใช่ JavaScript ได้ จากนั้นให้ Service Worker แสดงผล HTML สำหรับการนำทางหลังจากติดตั้งแล้ว ซึ่งจะช่วยให้คอมโพเนนต์และเทมเพลตที่แคชไว้เป็นเวอร์ชันล่าสุด และเปิดใช้การนําทางสไตล์ SPA เพื่อแสดงผลมุมมองใหม่ในเซสชันเดียวกัน วิธีนี้จะได้ผลดีที่สุดเมื่อคุณสามารถแชร์โค้ดการกำหนดเส้นทางและเทมเพลตเดียวกันระหว่างเซิร์ฟเวอร์ หน้าไคลเอ็นต์ และ Service Worker

การแสดงผลแบบ Trisomorphic ซึ่งแสดงให้เห็นเบราว์เซอร์และ Service Worker ที่สื่อสารกับเซิร์ฟเวอร์

ข้อควรพิจารณาเกี่ยวกับ SEO

เมื่อเลือกกลยุทธ์การแสดงผลเว็บ ทีมมักจะพิจารณาผลกระทบของ SEO การแสดงผลฝั่งเซิร์ฟเวอร์เป็นตัวเลือกยอดนิยมในการมอบประสบการณ์การใช้งานที่ "ดูสมบูรณ์" ซึ่ง Crawler สามารถตีความได้ Crawler เข้าใจ JavaScript แต่ก็มักจะมีข้อจำกัดในการแสดงผล การแสดงผลฝั่งไคลเอ็นต์สามารถทำงานได้ แต่ก็มักจะต้องมีการทดสอบและค่าใช้จ่ายเพิ่มเติม เมื่อไม่นานมานี้ การแสดงผลแบบไดนามิกก็เป็นอีกตัวเลือกหนึ่งที่น่าพิจารณาหากสถาปัตยกรรมของคุณต้องพึ่งพา JavaScript ฝั่งไคลเอ็นต์เป็นอย่างมาก

บทสรุป

เมื่อตัดสินใจเลือกแนวทางการแสดงผล ให้วัดและทำความเข้าใจว่าคอขวดคืออะไร พิจารณาว่าการแสดงผลแบบคงที่หรือการแสดงผลฝั่งเซิร์ฟเวอร์จะช่วยให้คุณบรรลุเป้าหมายส่วนใหญ่ได้หรือไม่ การส่ง HTML เป็นส่วนใหญ่โดยมี JavaScript เพียงเล็กน้อยเพื่อให้ได้ประสบการณ์แบบอินเทอร์แอกทีฟนั้นเป็นเรื่องปกติ อินโฟกราฟิกที่มีประโยชน์นี้แสดงสเปกตรัมของเซิร์ฟเวอร์-ไคลเอ็นต์

ตัวเลือกการแสดงผลและข้อดีข้อเสีย

เครดิต

ขอขอบคุณทุกคนสำหรับรีวิวและแรงบันดาลใจต่อไปนี้

Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson และ Sebastian Markbåge