การเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่สามใน Next.js

ทําความเข้าใจวิสัยทัศน์เบื้องหลังคอมโพเนนต์สคริปต์ของ Next.js ซึ่งให้โซลูชันในตัวเพื่อเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่สาม

คําขอจากเว็บไซต์ที่แสดงในอุปกรณ์เคลื่อนที่และเดสก์ท็อปประมาณ 45% เป็นคําขอของบุคคลที่สาม ซึ่ง33% เป็นสคริปต์ ขนาด เวลาในการตอบสนอง และการโหลดสคริปต์ของบุคคลที่สามอาจส่งผลต่อประสิทธิภาพของเว็บไซต์อย่างมาก คอมโพเนนต์สคริปต์ Next.js มีแนวทางปฏิบัติแนะนำและค่าเริ่มต้นที่พร้อมใช้งานเพื่อช่วยนักพัฒนาแอปในการนําสคริปต์ของบุคคลที่สามมาใช้ในแอปพลิเคชันของตน พร้อมทั้งแก้ปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้นได้ทันที

สคริปต์ของบุคคลที่สามและผลกระทบต่อประสิทธิภาพ

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

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

ควรโหลดไลบรารีของบุคคลที่สามที่จําเป็นสําหรับเลย์เอาต์ตั้งแต่เนิ่นๆ เพื่อแสดงผลหน้าเว็บ บุคคลที่สามที่ไม่จําเป็นสําหรับการแสดงผลเริ่มต้นควรเลื่อนออกไปเพื่อไม่ให้บล็อกการประมวลผลอื่นๆ ในเธรดหลัก Lighthouse มีการตรวจสอบ 2 รายการเพื่อแจ้งสคริปต์ที่บล็อกการแสดงผลหรือบล็อกชุดข้อความหลัก

การตรวจสอบของ Lighthouse สําหรับ "กำจัดทรัพยากรที่บล็อกการแสดงผล" และ "ลดการใช้ของบุคคลที่สาม"

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

แม้ว่าจะมีแนวทางปฏิบัติแนะนำในการลดผลกระทบของบุคคลที่สาม แต่ผู้ใช้บางรายอาจไม่ทราบวิธีใช้แนวทางปฏิบัติแนะนำกับบุคคลที่สามทุกรายที่ใช้ การดำเนินการนี้อาจมีความซับซ้อนเนื่องจากสาเหตุต่อไปนี้

  • โดยเฉลี่ยแล้ว เว็บไซต์ใช้บุคคลที่สามที่แตกต่างกัน 21-23 ราย รวมถึงสคริปต์ ในอุปกรณ์เคลื่อนที่และเดสก์ท็อป การใช้งานและคำแนะนำอาจแตกต่างกันไปในแต่ละรายการ
  • การใช้งานบุคคลที่สามหลายรายอาจแตกต่างกันไปโดยขึ้นอยู่กับว่ามีการใช้เฟรมเวิร์กหรือไลบรารี UI ใดหรือไม่
  • มีการเปิดตัวไลบรารีของบุคคลที่สามใหม่เป็นประจำ
  • ข้อกําหนดทางธุรกิจที่แตกต่างกันซึ่งเกี่ยวข้องกับบุคคลที่สามรายเดียวกันทําให้นักพัฒนาแอปใช้มาตรฐานเดียวกันได้ยาก

ความสนใจของสคริปต์ของบุคคลที่สามใน Aurora

การทำงานร่วมกันของ Aurora กับเฟรมเวิร์กและเครื่องมือเว็บแบบโอเพนซอร์สส่วนหนึ่งคือการมอบค่าเริ่มต้นที่มีประสิทธิภาพและเครื่องมือที่แสดงความคิดเห็นเพื่อช่วยนักพัฒนาแอปปรับปรุงแง่มุมต่างๆ ของประสบการณ์ของผู้ใช้ เช่น ประสิทธิภาพ การช่วยเหลือพิเศษ ความปลอดภัย และความพร้อมใช้งานบนอุปกรณ์เคลื่อนที่ ในปี 2021 เรามุ่งเน้นที่การช่วยให้แพ็กเกจเฟรมเวิร์กปรับปรุงประสบการณ์ของผู้ใช้และเมตริก Core Web Vitals

ขั้นตอนที่สําคัญที่สุดอย่างหนึ่งในการบรรลุเป้าหมายเพื่อปรับปรุงประสิทธิภาพเฟรมเวิร์กคือการค้นคว้าลําดับการโหลดสคริปต์ของบุคคลที่สามใน Next.js ที่เหมาะที่สุด เฟรมเวิร์กอย่าง Next.js อยู่ในจุดที่เหมาะเจาะในการมอบค่าเริ่มต้นและฟีเจอร์ที่มีประโยชน์ซึ่งช่วยให้นักพัฒนาแอปโหลดทรัพยากรได้อย่างมีประสิทธิภาพ รวมถึงทรัพยากรของบุคคลที่สาม เราได้ศึกษาข้อมูล HTTP Archive และ Lighthouse อย่างละเอียดเพื่อค้นหาว่าบุคคลที่สามรายใดบล็อกการแสดงผลมากที่สุดในเฟรมเวิร์กต่างๆ

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

การจัดลําดับสคริปต์ของบุคคลที่สามโดยไม่ใช้คอมโพเนนต์เฟรมเวิร์ก

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

  1. ใช้แอตทริบิวต์ async หรือ defer กับแท็ก <script> ที่บอกให้เบราว์เซอร์โหลดสคริปต์ของบุคคลที่สามที่ไม่สำคัญโดยไม่บล็อกโปรแกรมแยกวิเคราะห์เอกสาร สคริปต์ที่ไม่จำเป็นสำหรับการโหลดหน้าเว็บครั้งแรกหรือการโต้ตอบของผู้ใช้ครั้งแรกอาจถือว่าไม่สำคัญ

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. สร้างการเชื่อมต่อกับต้นทางที่จำเป็นตั้งแต่เนิ่นๆ โดยใช้การเชื่อมโยงล่วงหน้าและ dns-prefetch วิธีนี้ช่วยให้สคริปต์ที่สำคัญเริ่มดาวน์โหลดได้เร็วขึ้น

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. โหลดแบบ Lazy Loading ทรัพยากรและชิ้นงานของบุคคลที่สามหลังจากที่เนื้อหาในหน้าเว็บหลักโหลดเสร็จแล้ว หรือเมื่อผู้ใช้เลื่อนลงไปที่ส่วนที่มีชิ้นงานนั้นๆ

คอมโพเนนต์สคริปต์ Next.js

คอมโพเนนต์สคริปต์ Next.js ใช้เมธอดข้างต้นเพื่อจัดลำดับสคริปต์ และมีเทมเพลตสำหรับนักพัฒนาแอปในการกำหนดกลยุทธ์การโหลด เมื่อระบุกลยุทธ์ที่เหมาะสมแล้ว กลยุทธ์ดังกล่าวจะโหลดอย่างเหมาะสมโดยไม่บล็อกทรัพยากรสําคัญอื่นๆ

คอมโพเนนต์สคริปต์จะอิงตามแท็ก HTML <script> และมีตัวเลือกในการตั้งค่าลําดับความสําคัญในการโหลดสคริปต์ของบุคคลที่สามโดยใช้แอตทริบิวต์ strategy

// Example for beforeInteractive:
<Script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

แอตทริบิวต์กลยุทธ์มี 3 ค่า

  1. beforeInteractive: ตัวเลือกนี้อาจใช้สคริปต์ที่สำคัญซึ่งควรทำงานก่อนที่หน้าเว็บจะโต้ตอบได้ Next.js จะตรวจสอบว่าสคริปต์ดังกล่าวแทรกลงใน HTML เริ่มต้นบนเซิร์ฟเวอร์และดำเนินการก่อน JavaScript ที่รวมไว้เองอื่นๆ การจัดการความยินยอม สคริปต์การตรวจจับบ็อต หรือไลบรารีตัวช่วยที่จําเป็นสําหรับแสดงผลเนื้อหาสําคัญเหมาะสําหรับกลยุทธ์นี้

  2. afterInteractive: นี่เป็นกลยุทธ์เริ่มต้นที่ใช้และเทียบเท่ากับการโหลดสคริปต์ที่มีแอตทริบิวต์ defer ควรใช้กับสคริปต์ที่เบราว์เซอร์สามารถเรียกใช้ได้หลังจากที่หน้าเว็บมีการโต้ตอบ เช่น สคริปต์การวิเคราะห์ Next.js จะแทรกสคริปต์เหล่านี้ฝั่งไคลเอ็นต์และสคริปต์จะทํางานหลังจากที่หน้าเว็บได้รับการไฮเดรต ดังนั้น Next.js จะเลื่อนการโหลดสคริปต์ของบุคคลที่สามทั้งหมดที่กําหนดโดยใช้คอมโพเนนต์สคริปต์ เว้นแต่จะระบุไว้เป็นอย่างอื่น ซึ่งจะเป็นค่าเริ่มต้นที่มีประสิทธิภาพ

  3. lazyOnload: ตัวเลือกนี้อาจใช้เพื่อโหลดสคริปต์ที่มีลําดับความสําคัญต่ำแบบ Lazy Loading เมื่อเบราว์เซอร์ไม่ได้ใช้งาน ไม่จำเป็นต้องใช้ฟังก์ชันการทำงานจากสคริปต์ดังกล่าวทันทีที่หน้าเว็บเป็นแบบอินเทอร์แอกทีฟ เช่น ปลั๊กอินแชทหรือโซเชียลมีเดีย

นักพัฒนาแอปสามารถบอก Next.js ได้ว่าแอปพลิเคชันของตนใช้สคริปต์อย่างไรโดยระบุกลยุทธ์ ซึ่งช่วยให้เฟรมเวิร์กใช้การเพิ่มประสิทธิภาพและแนวทางปฏิบัติแนะนำเพื่อโหลดสคริปต์ไปพร้อมกับตรวจสอบลําดับการโหลดที่ดีที่สุด

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

การวัดผลลัพธ์

เราใช้เทมเพลตสำหรับแอป Commerce และบล็อกเริ่มต้นของ Next.js เพื่อสร้างแอปเดโม 2 แอปที่ช่วยวัดผลกระทบของการใช้สคริปต์ของบุคคลที่สาม บุคคลที่สามที่ใช้กันโดยทั่วไปสําหรับ Google Tag Manager และการฝังโซเชียลมีเดียจะรวมอยู่ในหน้าแอปเหล่านี้โดยตรงในตอนแรก จากนั้นจึงฝังผ่านคอมโพเนนต์สคริปต์ จากนั้นเราเปรียบเทียบประสิทธิภาพของหน้าเว็บเหล่านี้ใน WebPageTest

สคริปต์ของบุคคลที่สามในแอปคอมเมิร์ซ Next.js

มีการเพิ่มสคริปต์ของบุคคลที่สามลงในเทมเพลตแอป Commerce สำหรับการสาธิตตามที่ระบุไว้ด้านล่าง

ก่อน หลัง
Google Tag Manager แบบแอซิงค์ คอมโพเนนต์สคริปต์ที่มี strategy = afterInteractive สําหรับทั้ง 2 สคริปต์
ปุ่มติดตามของ Twitter ที่ไม่มีการทำงานแบบแอซิงค์หรือเลื่อน
การกําหนดค่าสคริปต์และคอมโพเนนต์สคริปต์สําหรับการสาธิต 1 ที่มีสคริปต์ 2 รายการ

การเปรียบเทียบต่อไปนี้แสดงความคืบหน้าของภาพสำหรับชุดเริ่มต้นใช้งาน Next.js Commerce ทั้ง 2 เวอร์ชัน ดังที่เห็น LCP เกิดขึ้นเร็วขึ้นเกือบ 1 วินาทีเมื่อเปิดใช้คอมโพเนนต์สคริปต์ด้วยกลยุทธ์การโหลดที่เหมาะสม

การเปรียบเทียบภาพสไลด์ที่แสดงการปรับปรุง LCP

สคริปต์ของบุคคลที่สามในบล็อก Next.js

เพิ่มสคริปต์ของบุคคลที่สามลงในแอปบล็อกเดโมตามที่ระบุไว้ด้านล่าง

ก่อน หลัง
Google Tag Manager แบบแอซิงค์ คอมโพเนนต์สคริปต์ที่มี strategy = lazyonload สําหรับสคริปต์แต่ละรายการ 4 รายการ
ปุ่มติดตามของ Twitter แบบแอซิงค์
ปุ่มติดตามของ YouTube แบบไม่ใช้ Async หรือเลื่อน
ปุ่มติดตามของ LinkedIn ที่ไม่มีการทำงานแบบแอซิงค์หรือเลื่อน
การกําหนดค่าสคริปต์และคอมโพเนนต์สคริปต์สําหรับการสาธิต 2 ที่มีสคริปต์ 4 รายการ
วิดีโอแสดงความคืบหน้าในการโหลดหน้าดัชนีที่มีและไม่มีคอมโพเนนต์สคริปต์ FCP ดีขึ้น 0.5 วินาทีเมื่อใช้คอมโพเนนต์สคริปต์

ดังที่เห็นในวิดีโอ First Contentful Paint (FCP) เกิดขึ้นที่ 0.9 วินาทีในหน้าเว็บที่ไม่มีคอมโพเนนต์สคริปต์ และ 0.4 วินาทีในหน้าเว็บที่มีคอมโพเนนต์สคริปต์

การพัฒนาคอมโพเนนต์สคริปต์ในอนาคต

แม้ว่าตัวเลือกกลยุทธ์สําหรับ afterInteractive และ lazyOnload จะมอบการควบคุมที่สําคัญเกี่ยวกับสคริปต์ที่บล็อกการแสดงผล แต่เรายังกําลังสํารวจตัวเลือกอื่นๆ ที่จะช่วยเพิ่มประโยชน์ของคอมโพเนนต์สคริปต์ด้วย

การใช้ผู้ปฏิบัติงานเกี่ยวกับเว็บ

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

เมื่อติดตั้งใช้งานคอมโพเนนต์สคริปต์ Next.js ในปัจจุบัน เราขอแนะนำให้เลื่อนเวลาสคริปต์เหล่านี้ในเธรดหลักโดยตั้งค่ากลยุทธ์เป็น afterInteractive หรือ lazyOnload ในอนาคต เราขอแนะนําให้เปิดตัวตัวเลือกกลยุทธ์ใหม่ 'worker' ซึ่งจะช่วยให้ Next.js ใช้ PartyTown หรือโซลูชันที่กําหนดเองเพื่อเรียกใช้สคริปต์ใน Web Worker ได้ เรายินดีรับฟังความคิดเห็นจากนักพัฒนาแอปเกี่ยวกับ RFC นี้

การลด CLS

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

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

คอมโพเนนต์ Wrapper

โดยทั่วไป ไวยากรณ์และกลยุทธ์การโหลดสําหรับการรวมสคริปต์ของบุคคลที่สามยอดนิยม เช่น Google Analytics หรือ Google Tag Manager (GTM) จะเป็นแบบคงที่ รายการเหล่านี้สามารถรวมไว้ในคอมโพเนนต์ Wrapper แต่ละรายการสำหรับสคริปต์แต่ละประเภท นักพัฒนาแอปจะมีสิทธิ์เข้าถึงแอตทริบิวต์เฉพาะแอปพลิเคชันเพียงชุดเล็กๆ (เช่น รหัสติดตาม) คอมโพเนนต์ Wrapper จะช่วยนักพัฒนาแอปในด้านต่อไปนี้

  1. ช่วยให้ผู้ใช้แท็กสคริปต์ยอดนิยมได้ง่ายขึ้น
  2. ตรวจสอบว่าเฟรมเวิร์กใช้กลยุทธ์ที่ดีที่สุด

บทสรุป

โดยปกติแล้วสคริปต์ของบุคคลที่สามจะสร้างขึ้นเพื่อรวมฟีเจอร์ที่เฉพาะเจาะจงไว้ในเว็บไซต์ที่ใช้งาน เราขอแนะนำให้เลื่อนเวลาการเรียกใช้สคริปต์ที่ไม่สำคัญออกไป ซึ่งคอมโพเนนต์สคริปต์ Next.js จะดำเนินการโดยค่าเริ่มต้น นักพัฒนาแอปมั่นใจได้ว่าสคริปต์ที่รวมไว้จะไม่ทำให้ฟังก์ชันการทํางานที่สําคัญล่าช้า เว้นแต่จะใช้กลยุทธ์ beforeInteractive อย่างชัดแจ้ง นักพัฒนาเฟรมเวิร์กยังพิจารณาสร้างฟีเจอร์เหล่านี้ในเฟรมเวิร์กอื่นๆ ได้ด้วย เช่นเดียวกับคอมโพเนนต์สคริปต์ Next.js เรากำลังสำรวจการนำคอมโพเนนต์ที่คล้ายกันมาใช้กับทีม Nuxt.js นอกจากนี้ เรายังหวังว่าจะปรับปรุงคอมโพเนนต์สคริปต์เพิ่มเติมเพื่อรองรับกรณีการใช้งานอื่นๆ ตามความคิดเห็นที่ได้รับ

บริการรับรองคำให้การ

ขอขอบคุณ Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner และ Addy Osmani ที่แสดงความคิดเห็นเกี่ยวกับโพสต์นี้