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

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

การแยกวิเคราะห์และแสดงผล HTML เป็นสิ่งที่เบราว์เซอร์ทำงานได้ดีโดยค่าเริ่มต้นสำหรับเว็บไซต์ที่ใช้ตรรกะการนำทางในตัวของเบราว์เซอร์ บางครั้งเรียกว่า "การโหลดหน้าเว็บแบบดั้งเดิม" หรือ "การนำทางอย่างเต็มที่" บางครั้งเราเรียกเว็บไซต์ลักษณะนี้ว่าแอปพลิเคชันแบบหลายหน้า (MPA)

อย่างไรก็ตาม นักพัฒนาซอฟต์แวร์อาจหลีกเลี่ยงค่าเริ่มต้นของเบราว์เซอร์เพื่อให้เหมาะกับความต้องการของแอปพลิเคชันของตน แน่นอนว่าเว็บไซต์ที่ใช้รูปแบบแอปพลิเคชันหน้าเว็บเดียว (SPA) ซึ่งจะสร้าง HTML/DOM ขนาดใหญ่ในไคลเอ็นต์ด้วย JavaScript ในแบบไดนามิก การแสดงผลฝั่งไคลเอ็นต์เป็นชื่อสำหรับรูปแบบการออกแบบนี้ และอาจมีผลต่อการโต้ตอบกับ Next Paint (INP) ของเว็บไซต์หากงานที่เกี่ยวข้องมากเกินไป

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

วิธีที่เบราว์เซอร์แสดงผล HTML ที่เซิร์ฟเวอร์ให้ไว้

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

  1. เบราว์เซอร์จะส่งคำขอการนำทางสำหรับ URL ที่ระบุ
  2. เซิร์ฟเวอร์จะตอบสนองด้วย HTML เป็นส่วนๆ

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

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

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

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

วิธีที่เบราว์เซอร์แสดงผล HTML ที่ JavaScript ให้ไว้

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

การแสดงผลฝั่งไคลเอ็นต์อาจเกิดขึ้นในที่ไม่ใช่ SpA ในกรณีที่จํากัดมากขึ้นซึ่งมีการเพิ่ม HTML ไปยัง DOM แบบไดนามิกผ่าน JavaScript

วิธีการทั่วไปในการสร้าง HTML หรือเพิ่มลงใน DOM ผ่าน JavaScript มีดังนี้

  1. พร็อพเพอร์ตี้ innerHTML ช่วยให้คุณตั้งค่าเนื้อหาในองค์ประกอบที่มีอยู่ผ่านสตริง ซึ่งเบราว์เซอร์จะแยกวิเคราะห์เป็น DOM
  2. เมธอด document.createElement ช่วยให้คุณสร้างองค์ประกอบใหม่ที่จะเพิ่มลงใน DOM ได้โดยไม่ต้องใช้การแยกวิเคราะห์ HTML ของเบราว์เซอร์
  3. เมธอด document.write ช่วยให้คุณเขียน HTML ลงในเอกสารได้ (และเบราว์เซอร์จะแยกวิเคราะห์ เช่นเดียวกับวิธีที่ 1) อย่างไรก็ตาม เราไม่แนะนำเป็นอย่างยิ่งให้ใช้ document.write เนื่องด้วยสาเหตุหลายประการ
ภาพหน้าจอแสดงการแยกวิเคราะห์ HTML ที่แสดงผลผ่าน JavaScript ซึ่งแสดงในแผงประสิทธิภาพของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome งานดังกล่าวจะเกิดขึ้นในงานที่ใช้เวลานานชิ้นเดียวซึ่งบล็อกเทรดหลัก
การแยกวิเคราะห์และแสดงผล HTML ผ่าน JavaScript ในไคลเอ็นต์ตามที่แสดงในแผงประสิทธิภาพของเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome งานที่เกี่ยวข้องกับการแยกวิเคราะห์และแสดงผลจะไม่มีการแบ่งเป็นส่วนๆ ทําให้เป็นงานที่ใช้เวลานานซึ่งจะบล็อกเทรดหลัก

ผลจากการสร้าง HTML/DOM ผ่าน JavaScript ฝั่งไคลเอ็นต์อาจมีนัยสำคัญดังนี้

  • งาน JavaScript บนไคลเอ็นต์จะไม่แบ่งเป็นส่วนๆ โดยอัตโนมัติ ซึ่งต่างจาก HTML ที่สตรีมโดยเซิร์ฟเวอร์เพื่อตอบสนองต่อคำขอการนำทาง ซึ่งอาจส่งผลให้งานใช้เวลาบล็อกเทรดหลัก ซึ่งหมายความว่า INP ของหน้าเว็บอาจได้รับผลกระทบในทางลบหากคุณสร้าง HTML/DOM มากเกินไปในไคลเอ็นต์ในแต่ละครั้ง
  • หากสร้าง HTML บนไคลเอ็นต์ในระหว่างการเริ่มต้น ทรัพยากรที่อ้างอิงภายในไคลเอ็นต์จะไม่ค้นพบโดยเครื่องสแกนการโหลดล่วงหน้าของเบราว์เซอร์ ซึ่งจะส่งผลเสียต่อการแสดงผลเนื้อหาขนาดใหญ่ที่สุด (LCP) ของหน้าเว็บอย่างแน่นอน แม้ว่านี่จะไม่ใช่ปัญหาด้านประสิทธิภาพรันไทม์ (แต่เป็นปัญหาเกี่ยวกับความล่าช้าของเครือข่ายในการดึงข้อมูลทรัพยากรที่สำคัญ) แต่คุณไม่ต้องการให้ LCP ของเว็บไซต์ได้รับผลกระทบจากการเพิ่มประสิทธิภาพการทำงานของเบราว์เซอร์พื้นฐานนี้

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

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

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

ระบุ HTML จากเซิร์ฟเวอร์ให้ได้มากที่สุด

อย่างที่ได้กล่าวไปแล้วก่อนหน้านี้ เบราว์เซอร์จะจัดการ HTML จากเซิร์ฟเวอร์ได้อย่างมีประสิทธิภาพมากโดยค่าเริ่มต้น ซึ่งจะแบ่งการแยกวิเคราะห์และการแสดงผลของ HTML ในลักษณะที่หลีกเลี่ยงงานที่ใช้เวลานาน และเพิ่มประสิทธิภาพระยะเวลาทั้งหมดของเทรดหลัก ซึ่งทำให้มีเวลาในการบล็อกทั้งหมด (TBT) ต่ำลง และ TBT มีความสัมพันธ์อย่างมากกับ INP

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

  • สำหรับ React คุณจะต้องใช้ Server DOM API ในการแสดงผล HTML บนเซิร์ฟเวอร์ แต่อย่าลืมว่าวิธีการแสดงผลฝั่งเซิร์ฟเวอร์แบบดั้งเดิมใช้วิธีการแบบซิงโครนัส ซึ่งอาจทำให้ใช้เวลาเป็นไบต์แรก (TTFB) ได้นานขึ้น รวมถึงเมตริกที่ตามมา เช่น First Contentful Paint (FCP) และ LCP หากเป็นไปได้ ให้ตรวจสอบว่าคุณใช้ API สตรีมมิงสำหรับ Node.js หรือรันไทม์ของ JavaScript อื่นๆ เพื่อให้เซิร์ฟเวอร์เริ่มสตรีม HTML ไปยังเบราว์เซอร์ได้โดยเร็วที่สุด Next.js ซึ่งเป็นเฟรมเวิร์กแบบ React นำเสนอแนวทางปฏิบัติแนะนำมากมายโดยค่าเริ่มต้น นอกจากการแสดงผล HTML โดยอัตโนมัติบนเซิร์ฟเวอร์แล้ว เครื่องมือนี้ยังสามารถสร้าง HTML แบบคงที่สำหรับหน้าเว็บที่ไม่มีการเปลี่ยนแปลงตามบริบทของผู้ใช้ (เช่น การตรวจสอบสิทธิ์)
  • นอกจากนี้ Vue แสดงผลฝั่งไคลเอ็นต์โดยค่าเริ่มต้นด้วย อย่างไรก็ตาม Vue สามารถแสดงผล HTML ของคอมโพเนนต์ในเซิร์ฟเวอร์ได้เช่นเดียวกับ React ใช้ประโยชน์จาก API ฝั่งเซิร์ฟเวอร์เหล่านี้เมื่อเป็นไปได้ หรือลองใช้Abstraction ระดับสูงขึ้นสําหรับโปรเจ็กต์ Vue ของคุณเพื่อให้นําแนวทางปฏิบัติแนะนําไปใช้ได้ง่ายขึ้น
  • Svelte จะแสดง HTML บนเซิร์ฟเวอร์โดยค่าเริ่มต้น แม้ว่าโค้ดคอมโพเนนต์จำเป็นต้องเข้าถึงเนมสเปซเฉพาะเบราว์เซอร์ (เช่น window) คุณอาจไม่สามารถแสดงผล HTML ของคอมโพเนนต์ดังกล่าวบนเซิร์ฟเวอร์ได้ ลองหาวิธีอื่นๆ หากเป็นไปได้ เพื่อไม่ให้เกิดการแสดงผลฝั่งไคลเอ็นต์ที่ไม่จำเป็น SvelteKit ซึ่งก็คือ Svelte ในรูปแบบ Next.js ที่จะทำเป็น React ฝังแนวทางปฏิบัติแนะนำหลายๆ ข้อไว้ในโปรเจ็กต์ Svelte ของคุณเท่าที่จะเป็นไปได้ เพื่อหลีกเลี่ยงข้อผิดพลาดที่อาจเกิดขึ้นในโปรเจ็กต์ที่ใช้ Svelte เพียงอย่างเดียว

จำกัดจำนวนโหนด DOM ที่สร้างขึ้นในไคลเอ็นต์

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

พิจารณาใช้สถาปัตยกรรมของ Service Worker สตรีมมิง

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

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

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

บทสรุป

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

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

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

รูปภาพหลักจาก Unsplash โดย Maik Jonietz