การเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่สามใน 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 ล่วงหน้า ซึ่งจะทำให้สคริปต์ที่สำคัญเริ่มดาวน์โหลดได้เร็วขึ้น

       <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> และมีตัวเลือกในการตั้งค่าลำดับความสำคัญในการโหลดสำหรับสคริปต์ของบุคคลที่สามโดยใช้แอตทริบิวต์กลยุทธ์

// 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: กลยุทธ์นี้เป็นกลยุทธ์เริ่มต้นและเทียบเท่ากับการโหลดสคริปต์ที่มีแอตทริบิวต์ที่เลื่อนเวลาออกไป ควรใช้สำหรับสคริปต์ที่เบราว์เซอร์สามารถเรียกใช้หลังจากที่หน้าเว็บมีการโต้ตอบ เช่น สคริปต์การวิเคราะห์ Next.js จะแทรกสคริปต์เหล่านี้ในฝั่งไคลเอ็นต์และจะทำงานหลังจากที่หน้าเว็บได้รับการเติมน้ำแล้ว ดังนั้น Next.js จะเลื่อนเวลาสคริปต์ของบุคคลที่สามทั้งหมดที่กำหนดโดยใช้คอมโพเนนต์สคริปต์ และให้ค่าเริ่มต้นที่แข็งแกร่ง เว้นแต่จะระบุไว้เป็นอย่างอื่น

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

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

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

การวัดผลกระทบ

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

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

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

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

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

การเปรียบเทียบแถบฟิล์มที่แสดงการด้นสดใน LCP

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

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

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

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

ขั้นตอนถัดไปสำหรับคอมโพเนนต์สคริปต์

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

การใช้ Web Worker

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

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

การลด CLS

การฝังของบุคคลที่สาม เช่น โฆษณา วิดีโอ หรือการฝังฟีดโซเชียลมีเดียอาจทำให้เลย์เอาต์เกิดการเปลี่ยนแปลงเมื่อโหลดแบบ Lazy Loading ซึ่งจะส่งผลต่อประสบการณ์ของผู้ใช้และเมตริก Cumulative Layout Shift (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 สำหรับความคิดเห็นเกี่ยวกับโพสต์นี้