รายการตรวจสอบประสิทธิภาพ Front-End 2021 (PDF, Apple Pages, MS Word)

เผยแพร่แล้ว: 2022-03-10
สรุปด่วน ↬ มาสร้างปี 2021… ให้ไว! รายการตรวจสอบประสิทธิภาพของฟรอนต์เอนด์ประจำปี (มีให้ใช้งานในรูปแบบ PDF, Apple Pages, MS Word) พร้อมทุกสิ่งที่คุณจำเป็นต้องรู้เพื่อสร้างประสบการณ์การใช้งานที่รวดเร็วบนเว็บในปัจจุบัน ตั้งแต่ตัววัดไปจนถึงเครื่องมือและเทคนิคส่วนหน้า อัปเดตตั้งแต่ปี 2016 อ้อ คุณสามารถรับคำแนะนำที่เป็นประโยชน์ส่วนหน้าในจดหมายข่าวทางอีเมลของเราได้

ประสิทธิภาพของเว็บเป็นสัตว์ร้ายใช่ไหม เราจะรู้ได้อย่างไร ว่า เรายืนอยู่ตรงไหนในแง่ของประสิทธิภาพ และปัญหาคอขวดด้านประสิทธิภาพของเราคืออะไรกันแน่? JavaScript มีราคาแพง การส่งฟอนต์เว็บช้า รูปภาพหนัก หรือการเรนเดอร์ที่เชื่องช้าหรือไม่ เราได้ปรับให้เหมาะสมเพียงพอแล้วกับการเขย่าต้นไม้ การยกขอบเขต การแยกรหัส และรูปแบบการโหลดที่สวยงามพร้อมตัวสังเกตทางแยก การไฮเดรชันแบบก้าวหน้า คำแนะนำลูกค้า HTTP/3 พนักงานบริการ และ — โอ้ ฉัน — พนักงาน edge หรือไม่ และที่สำคัญที่สุด เราจะเริ่มปรับปรุงประสิทธิภาพได้ จากที่ไหน และเราจะสร้างวัฒนธรรมการแสดงในระยะยาวได้อย่างไร

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

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

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

สารบัญ

  • ทั้งหมดอยู่ในหน้าแยกต่างหาก
  • เตรียมตัวให้พร้อม: การวางแผนและการวัดผล
    วัฒนธรรมประสิทธิภาพ, Core Web Vitals, โปรไฟล์ประสิทธิภาพ, CrUX, Lighthouse, FID, TTI, CLS, อุปกรณ์
  • การตั้งเป้าหมายที่สมจริง
    งบประมาณประสิทธิภาพ เป้าหมายประสิทธิภาพ เฟรมเวิร์ก RAIL งบประมาณ 170KB/30KB
  • การกำหนดสภาพแวดล้อม
    การเลือกเฟรมเวิร์ก, ต้นทุนประสิทธิภาพพื้นฐาน, Webpack, การพึ่งพา, CDN, สถาปัตยกรรมส่วนหน้า, CSR, SSR, CSR + SSR, การเรนเดอร์สแตติก, การเรนเดอร์ล่วงหน้า, รูปแบบ PRPL
  • การเพิ่มประสิทธิภาพสินทรัพย์
    Brotli, AVIF, WebP, รูปภาพที่ตอบสนอง, AV1, การโหลดสื่อที่ปรับเปลี่ยนได้, การบีบอัดวิดีโอ, แบบอักษรเว็บ, แบบอักษร Google
  • สร้างการเพิ่มประสิทธิภาพ
    โมดูล JavaScript, รูปแบบโมดูล/โนโมดูล, การสั่นต้นไม้, การแยกโค้ด, การยกขอบเขต, Webpack, การให้บริการที่แตกต่างกัน, ผู้ปฏิบัติงานบนเว็บ, WebAssembly, กลุ่ม JavaScript, React, SPA, ความชุ่มชื้นบางส่วน, การนำเข้าจากการโต้ตอบ, บุคคลที่สาม, แคช
  • การเพิ่มประสิทธิภาพการจัดส่ง
    โหลดช้า, ผู้สังเกตการณ์ทางแยก, เลื่อนการแสดงผลและถอดรหัส, CSS ที่สำคัญ, การสตรีม, คำแนะนำทรัพยากร, การเปลี่ยนเลย์เอาต์, พนักงานบริการ
  • เครือข่าย, HTTP/2, HTTP/3
    เย็บกระดาษ OCSP, ใบรับรอง EV/DV, บรรจุภัณฑ์, IPv6, QUIC, HTTP/3
  • การทดสอบและการตรวจสอบ
    เวิร์กโฟลว์การตรวจสอบ, เบราว์เซอร์พร็อกซี่, หน้า 404, ข้อความแจ้งความยินยอมของคุกกี้ GDPR, CSS การวินิจฉัยประสิทธิภาพ, การเข้าถึง
  • ชนะอย่างรวดเร็ว
  • ดาวน์โหลดรายการตรวจสอบ (PDF, Apple Pages, MS Word)
  • เราไปกันเถอะ!

(คุณยังสามารถดาวน์โหลดไฟล์ตรวจสอบ PDF (166 KB) หรือดาวน์โหลดไฟล์ Apple Pages ที่แก้ไขได้ (275 KB) หรือไฟล์ .docx (151 KB) ขอให้สนุกกับการเพิ่มประสิทธิภาพทุกคน!)

เตรียมตัวให้พร้อม: การวางแผนและการวัดผล

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

  1. สร้างวัฒนธรรมการแสดง
    ในหลายองค์กร นักพัฒนาส่วนหน้ารู้ว่าปัญหาพื้นฐานทั่วไปคืออะไร และควรใช้กลยุทธ์ใดในการแก้ไขปัญหา อย่างไรก็ตาม ตราบใดที่ยังไม่มีการรับรองวัฒนธรรมการปฏิบัติงาน การตัดสินใจแต่ละครั้งจะกลายเป็นสนามรบของแผนกต่างๆ แบ่งองค์กรออกเป็นไซโล คุณต้องซื้อผู้มีส่วนได้ส่วนเสียทางธุรกิจ และเพื่อให้ได้มานี้ คุณต้องสร้างกรณีศึกษาหรือหลักฐานของแนวคิดเกี่ยวกับความเร็ว — โดยเฉพาะ Core Web Vitals ที่เราจะกล่าวถึงในรายละเอียดในภายหลัง — ตัวชี้วัดประโยชน์และตัวชี้วัดประสิทธิภาพหลัก ( KPIs ) ที่พวกเขาใส่ใจ

    ตัวอย่างเช่น เพื่อให้ประสิทธิภาพเป็นรูปธรรมมากขึ้น คุณสามารถเปิดเผยผลกระทบต่อประสิทธิภาพรายได้โดยแสดงความสัมพันธ์ระหว่างอัตราการแปลงและเวลาในการโหลดแอปพลิเคชัน ตลอดจนประสิทธิภาพการแสดงผล หรืออัตราการรวบรวมข้อมูลของบอทการค้นหา (PDF, หน้า 27–50)

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

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

    วิธีการเดินทาง? ในการพูดคุยของเธอเกี่ยวกับการสร้างประสิทธิภาพสำหรับระยะยาว Allison McKnight ได้แบ่งปันกรณีศึกษาที่ครอบคลุมถึงวิธีที่เธอช่วยสร้างวัฒนธรรมการแสดงที่ Etsy (สไลด์) เมื่อไม่นานมานี้ Tammy Everts ได้พูดถึงนิสัยของทีมที่มีประสิทธิภาพสูงทั้งในองค์กรขนาดเล็กและขนาดใหญ่

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

บนอุปกรณ์เคลื่อนที่ ต่อเซสชัน ผู้ใช้ที่ประสบปัญหาเวลาในการโหลดเร็วจะสร้างรายได้มากกว่าค่าเฉลี่ยถึง 17%
บนอุปกรณ์เคลื่อนที่ ต่อเซสชัน ผู้ใช้ที่มีประสบการณ์การโหลดที่รวดเร็วจะสร้างรายได้มากกว่าค่าเฉลี่ย 17% (ผลกระทบของประสิทธิภาพเว็บ โดย Addy Osmani)
การคาดหวังให้ตัวเลขเดียวสามารถให้คะแนนที่ต้องการนั้นเป็นข้อสมมติที่มีข้อบกพร่อง
การคาดหวังให้ตัวเลขเดียวสามารถให้คะแนนที่ต้องการได้นั้นเป็นข้อสมมติที่มีข้อบกพร่อง (เครดิตรูปภาพ: ประสิทธิภาพคือการแจกจ่ายผ่าน Karolina Czczur)
  1. เป้าหมาย: เร็วกว่าคู่แข่งที่เร็วที่สุดของคุณอย่างน้อย 20%
    จากการวิจัยทางจิตวิทยา หากคุณต้องการให้ผู้ใช้รู้สึกว่าเว็บไซต์ของคุณเร็วกว่าเว็บไซต์ของคู่แข่ง คุณจะต้องเร็วกว่า อย่างน้อย 20% ศึกษาคู่แข่งหลักของคุณ รวบรวมตัวชี้วัดว่าพวกเขาทำงานอย่างไรบนมือถือและเดสก์ท็อป และตั้งเกณฑ์ที่จะช่วยให้คุณแซงหน้าพวกเขา เพื่อให้ได้ผลลัพธ์และเป้าหมายที่ถูกต้อง ก่อนอื่นต้องแน่ใจว่าได้เห็นภาพประสบการณ์ของผู้ใช้อย่างละเอียดโดยศึกษาการวิเคราะห์ของคุณ จากนั้น คุณสามารถเลียนแบบประสบการณ์ของเปอร์เซ็นไทล์ที่ 90 สำหรับการทดสอบได้

    คุณสามารถใช้ Chrome UX Report ( CrUX ชุดข้อมูล RUM สำเร็จรูป วิดีโอแนะนำโดย Ilya Grigorik และคำแนะนำโดยละเอียดโดย Rick Viscomi) หรือ Treo เครื่องมือตรวจสอบ RUM ขับเคลื่อนโดยรายงาน Chrome UX ข้อมูลถูกรวบรวมจากผู้ใช้เบราว์เซอร์ Chrome ดังนั้นรายงานจะเป็นแบบเฉพาะสำหรับ Chrome แต่รายงานเหล่านี้จะช่วยให้คุณมีการกระจายประสิทธิภาพที่ละเอียดถี่ถ้วน ที่สำคัญที่สุดคือคะแนน Core Web Vitals สำหรับผู้เยี่ยมชมที่หลากหลาย โปรดทราบว่าชุดข้อมูล CrUX ใหม่จะออกใน วันอังคารที่สองของแต่ละเดือน

    หรือคุณสามารถใช้:

    • เครื่องมือเปรียบเทียบรายงาน Chrome UX ของ Addy Osmani
    • Speed ​​Scorecard (ยังมีตัวประมาณผลกระทบด้านรายได้)
    • การเปรียบเทียบการทดสอบประสบการณ์ผู้ใช้จริงหรือ
    • SiteSpeed ​​CI (อิงจากการทดสอบสังเคราะห์)

    หมายเหตุ : หากคุณใช้ Page Speed ​​Insights หรือ Page Speed ​​Insights API (ไม่ ไม่มีการเลิกใช้งาน!) คุณจะได้รับข้อมูลประสิทธิภาพ CrUX สำหรับหน้าใดหน้าหนึ่ง แทนที่จะเป็นเพียงการรวม ข้อมูลนี้อาจมีประโยชน์มากขึ้นในการกำหนดเป้าหมายด้านประสิทธิภาพสำหรับเนื้อหา เช่น "หน้า Landing Page" หรือ "รายการผลิตภัณฑ์" และหากคุณใช้ CI เพื่อทดสอบงบประมาณ คุณต้องแน่ใจว่าสภาพแวดล้อมที่ทดสอบของคุณตรงกับ CrUX หากคุณใช้ CrUX ในการกำหนดเป้าหมาย ( ขอบคุณ Patrick Meenan! )

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

    CrUX สร้างภาพรวมของการกระจายประสิทธิภาพเมื่อเวลาผ่านไป โดยมีการรับส่งข้อมูลที่รวบรวมจากผู้ใช้ Google Chrome
    CrUX สร้างภาพรวมของการกระจายประสิทธิภาพเมื่อเวลาผ่านไป โดยมีการรับส่งข้อมูลที่รวบรวมจากผู้ใช้ Google Chrome คุณสามารถสร้างของคุณเองได้บน Chrome UX Dashboard (ตัวอย่างขนาดใหญ่)
    เมื่อคุณต้องการสร้างกรณีสำหรับประสิทธิภาพเพื่อขับเคลื่อนประเด็นของคุณ: UX Speed ​​Calculator แสดงภาพผลกระทบของประสิทธิภาพต่ออัตราตีกลับ การแปลง และรายได้ทั้งหมด โดยอิงจากข้อมูลจริง
    เมื่อคุณต้องการสร้างกรณีสำหรับประสิทธิภาพเพื่อขับเคลื่อนประเด็นของคุณ: UX Speed ​​Calculator จะแสดงภาพผลกระทบของประสิทธิภาพต่ออัตราตีกลับ การแปลง และรายได้ทั้งหมด โดยอิงจากข้อมูลจริง (ตัวอย่างขนาดใหญ่)

    บางครั้งคุณอาจต้องการเจาะลึกลงไปอีกเล็กน้อย โดยการรวมข้อมูลที่มาจาก CrUX กับข้อมูลอื่นๆ ที่คุณต้องดำเนินการอย่างรวดเร็วในจุดที่เกิดการชะลอตัว จุดบอด และความไร้ประสิทธิภาพ - สำหรับคู่แข่งของคุณหรือสำหรับโครงการของคุณ ในงานของเขา แฮร์รี่ โรเบิร์ตส์ใช้สเปรดชีตภูมิประเทศความเร็วไซต์ ซึ่งเขาใช้ในการแบ่งประสิทธิภาพตามประเภทเพจหลัก และติดตามว่าเมตริกหลักต่างๆ แตกต่างกันอย่างไร คุณสามารถดาวน์โหลดสเปรดชีตเป็น Google ชีต, Excel, เอกสาร OpenOffice หรือ CSV

    ภูมิประเทศความเร็วไซต์พร้อมตัวชี้วัดหลักที่แสดงสำหรับหน้าสำคัญบนไซต์
    ภูมิประเทศความเร็วของไซต์ พร้อมตัวชี้วัดหลักที่แสดงสำหรับหน้าสำคัญบนไซต์ (ตัวอย่างขนาดใหญ่)

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

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

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

    ต้องการทรัพยากรเพื่อเริ่มต้น?

    • Addy Osmani ได้เขียนบทความโดยละเอียดเกี่ยวกับวิธีเริ่มต้นการจัดทำงบประมาณประสิทธิภาพ วิธีวัดผลกระทบของคุณลักษณะใหม่ และจุดเริ่มต้นเมื่อคุณใช้งบประมาณเกิน
    • คู่มือของ Lara Hogan เกี่ยวกับวิธีการออกแบบด้วยงบประมาณด้านประสิทธิภาพสามารถให้คำแนะนำที่เป็นประโยชน์แก่นักออกแบบได้
    • Harry Roberts ได้เผยแพร่คู่มือการตั้งค่า Google ชีตเพื่อแสดงผลกระทบของสคริปต์ของบุคคลที่สามที่มีต่อประสิทธิภาพ โดยใช้ Request Map
    • เครื่องคำนวณงบประมาณด้านประสิทธิภาพของ Jonathan Fielding เครื่องคำนวณงบประมาณที่สมบูรณ์แบบของ Katie Hempenius และแคลอรี่ของเบราว์เซอร์สามารถช่วยในการสร้างงบประมาณได้ (ขอบคุณ Karolina Szczur สำหรับการเตือนล่วงหน้า)
    • ในหลายบริษัท งบประมาณด้านประสิทธิภาพไม่ควรเป็นแรงบันดาลใจ แต่ควรนำไปใช้ได้จริง เพื่อเป็นสัญญาณบ่งชี้เพื่อหลีกเลี่ยงไม่ให้ผ่านจุดใดจุดหนึ่ง ในกรณีนั้น คุณสามารถเลือกจุดข้อมูลที่เลวร้ายที่สุดในช่วงสองสัปดาห์ที่ผ่านมาเป็นเกณฑ์ แล้วนำจุดข้อมูลนั้นออกจากจุดนั้น งบประมาณประสิทธิภาพ แสดงกลยุทธ์เพื่อให้บรรลุผลในทางปฏิบัติในทางปฏิบัติ
    • อีกทั้งทำให้ทั้งงบประมาณประสิทธิภาพและประสิทธิภาพปัจจุบัน มองเห็นได้ โดยการตั้งค่าแดชบอร์ดพร้อมกราฟขนาดการสร้างการรายงาน มีเครื่องมือมากมายที่ช่วยให้คุณบรรลุเป้าหมายดังกล่าว: แดชบอร์ด SiteSpeed.io (โอเพ่นซอร์ส) SpeedCurve และ Caliber เป็นเพียงไม่กี่เครื่องมือ และคุณสามารถหาเครื่องมือเพิ่มเติมบน perf.rocks
    เบราว์เซอร์แคลอรี่ช่วยให้คุณกำหนดงบประมาณประสิทธิภาพและวัดว่าหน้าเกินตัวเลขเหล่านี้หรือไม่
    แคลอรี่ของเบราว์เซอร์ช่วยให้คุณกำหนดงบประมาณประสิทธิภาพและวัดว่าหน้าใดเกินตัวเลขเหล่านี้หรือไม่ (ตัวอย่างขนาดใหญ่)

    เมื่อคุณมีงบประมาณแล้ว ให้รวมไว้ในขั้นตอนการสร้างของคุณด้วย Webpack Performance Hints and Bundlesize, Lighthouse CI, PWMetrics หรือ Sitespeed CI เพื่อบังคับใช้งบประมาณในคำขอดึงและจัดทำประวัติคะแนนในความคิดเห็นของ PR

    หากต้องการเปิดเผยงบประมาณด้านประสิทธิภาพให้กับทั้งทีม ให้รวมงบประมาณประสิทธิภาพใน Lighthouse ผ่าน Lightwallet หรือใช้ LHCI Action สำหรับการผสานรวม Github Actions อย่างรวดเร็ว และถ้าคุณต้องการสิ่งที่กำหนดเอง คุณสามารถใช้ webPagetest-charts-api ซึ่งเป็น API ของปลายทางเพื่อสร้างแผนภูมิจากผลลัพธ์ WebPagetest

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

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

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

    ตามที่ Patrick Meenan แนะนำ คุณควร วางแผนลำดับการโหลดและการแลกเปลี่ยน ระหว่างกระบวนการออกแบบ หากคุณจัดลำดับความสำคัญแต่เนิ่นๆ ว่าส่วนใดมีความสำคัญมากกว่า และกำหนดลำดับที่ส่วนเหล่านั้นควรปรากฏ คุณจะรู้ด้วยว่าสิ่งใดที่อาจล่าช้าได้ ตามหลักการแล้ว ลำดับดังกล่าวจะสะท้อนถึงลำดับการนำเข้า CSS และ JavaScript ของคุณ ดังนั้นการจัดการระหว่างกระบวนการสร้างจะง่ายขึ้น นอกจากนี้ ให้พิจารณาว่าประสบการณ์การมองเห็นควรเป็นอย่างไรในสถานะ "ระหว่าง" ในขณะที่กำลังโหลดหน้าเว็บ (เช่น เมื่อยังไม่ได้โหลดแบบอักษรของเว็บ)

    เมื่อคุณได้สร้างวัฒนธรรมการปฏิบัติงานที่แข็งแกร่งในองค์กรของคุณแล้ว ให้ตั้งเป้าว่าจะต้อง เร็วกว่าตัวตนเดิมของคุณ 20% เพื่อรักษาลำดับความสำคัญไว้เมื่อเวลาผ่านไป ( ขอบคุณ Guy Podjarny! ) แต่ให้คำนึงถึงประเภทและพฤติกรรมการใช้งานที่แตกต่างกันของลูกค้าของคุณ (ซึ่ง Tobias Baldauf เรียกว่า cadence และ cohorts) พร้อมกับปริมาณการใช้บอทและผลกระทบตามฤดูกาล

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

Treo Sites ให้การวิเคราะห์การแข่งขันโดยอิงจากข้อมูลในโลกแห่งความเป็นจริง
Treo ให้การวิเคราะห์การแข่งขันโดยอิงจากข้อมูลในโลกแห่งความเป็นจริง (ตัวอย่างขนาดใหญ่)
ตัวชี้วัดใหม่มาถึง Lighthouse v6 ในต้นปี 2020
ตัวชี้วัดใหม่มาถึง Lighthouse v6 ในต้นปี 2020 (ตัวอย่างขนาดใหญ่)
  1. เลือกตัวชี้วัดที่เหมาะสม
    เมตริกทั้งหมดไม่ได้มีความสำคัญเท่าเทียมกัน ศึกษาเมตริกที่สำคัญที่สุดสำหรับแอปพลิเคชันของคุณ: โดยปกติ จะกำหนดเมตริกโดยความรวดเร็วในการเริ่มแสดง พิกเซลที่สำคัญที่สุดในอินเทอร์เฟซของคุณ และความรวดเร็วในการ ตอบสนองต่ออินพุต สำหรับพิกเซลที่แสดงผลเหล่านี้ ความรู้นี้จะทำให้คุณมีเป้าหมายในการเพิ่มประสิทธิภาพที่ดีที่สุดสำหรับความพยายามอย่างต่อเนื่อง ในท้ายที่สุด ไม่ใช่เหตุการณ์การโหลดหรือเวลาตอบสนองของเซิร์ฟเวอร์ที่กำหนดประสบการณ์ แต่เป็นการรับรู้ว่าอินเทอร์เฟซ รู้สึก รวดเร็วเพียงใด

    มันหมายความว่าอะไร? แทนที่จะเน้นที่เวลาในการโหลดแบบเต็มหน้า (เช่น ผ่านการกำหนดเวลา onLoad และ DOMContentLoaded ) ให้จัดลำดับความสำคัญในการโหลดหน้าเว็บตามที่ลูกค้าของคุณรับรู้ นั่นหมายถึงการมุ่งเน้นไปที่ชุดเมตริกที่แตกต่างกันเล็กน้อย อันที่จริง การเลือกเมตริกที่ถูกต้องเป็นกระบวนการที่ไม่มีผู้ชนะที่ชัดเจน

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

    • เมตริกตาม ปริมาณจะวัดจำนวนคำขอ น้ำหนัก และคะแนนประสิทธิภาพ เหมาะสำหรับการเตือนและตรวจสอบการเปลี่ยนแปลงเมื่อเวลาผ่านไป ไม่ดีสำหรับการทำความเข้าใจประสบการณ์ของผู้ใช้
    • เมตริก Milestone ใช้สถานะในช่วงอายุของกระบวนการโหลด เช่น Time To First Byte และ Time To Interactive เหมาะสำหรับการอธิบายประสบการณ์ของผู้ใช้และการตรวจสอบ ไม่ดีนักสำหรับการรู้ว่าเกิดอะไรขึ้นระหว่างเหตุการณ์สำคัญ
    • การวัดการแสดงผล จะให้ค่าประมาณความเร็วในการแสดงเนื้อหา (เช่น เวลา เริ่มการเรนเดอ ร์ ดัชนีความเร็ว ) ดีสำหรับการวัดและปรับแต่งประสิทธิภาพการเรนเดอร์ แต่ไม่ดีสำหรับการวัดเมื่อเนื้อหา สำคัญ ปรากฏขึ้นและสามารถโต้ตอบได้
    • ตัววัดแบบกำหนดเองจะ วัดเหตุการณ์เฉพาะ เหตุการณ์ที่กำหนดเองสำหรับผู้ใช้ เช่น Twitter's Time To First Tweet และ PinnerWaitTime ของ Pinterest ดีสำหรับการอธิบายประสบการณ์ผู้ใช้อย่างแม่นยำ ไม่ดีสำหรับการปรับขนาดตัวชี้วัดและเปรียบเทียบกับคู่แข่ง

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

    • เวลาในการโต้ตอบ (TTI)
      จุดที่เลย์เอาต์มี เสถียรภาพ มองเห็นคีย์เว็บฟอนต์ และเธรดหลักพร้อมใช้งานเพียงพอที่จะจัดการกับอินพุตของผู้ใช้ โดยพื้นฐานแล้วจะเป็นเครื่องหมายเวลาที่ผู้ใช้สามารถโต้ตอบกับ UI ได้ ตัวชี้วัดที่สำคัญสำหรับการทำความเข้าใจว่าผู้ใช้ ต้องรอนาน เพียงใดเพื่อใช้เว็บไซต์โดยไม่เกิดความล่าช้า Boris Schapira ได้เขียนโพสต์โดยละเอียดเกี่ยวกับวิธีการวัด TTI อย่างน่าเชื่อถือ
    • First Input Delay (FID) หรือการ ตอบสนองต่ออินพุต
      เวลาที่ผู้ใช้โต้ตอบกับไซต์ของคุณเป็นครั้งแรกจนถึงเวลาที่เบราว์เซอร์ สามารถตอบสนองต่อ การโต้ตอบนั้นได้จริง ช่วยเสริม TTI ได้เป็นอย่างดีเนื่องจากอธิบายส่วนที่ขาดหายไปของรูปภาพ: จะเกิดอะไรขึ้นเมื่อผู้ใช้โต้ตอบกับไซต์จริง ตั้งใจให้เป็นตัวชี้วัด RUM เท่านั้น มีไลบรารี JavaScript สำหรับวัด FID ในเบราว์เซอร์
    • Largest Contentful Paint (LCP)
      ทำเครื่องหมายจุดในไทม์ไลน์การโหลดหน้าเว็บเมื่อ เนื้อหาสำคัญ ของหน้าน่าจะโหลดขึ้น สมมติฐานคือองค์ประกอบที่สำคัญที่สุดของหน้าคือองค์ประกอบที่ใหญ่ที่สุดที่มองเห็นได้ในวิวพอร์ตของผู้ใช้ หากองค์ประกอบแสดงทั้งด้านบนและด้านล่างครึ่งหน้าล่าง จะถือว่าเฉพาะส่วนที่มองเห็นได้เท่านั้นที่เกี่ยวข้อง
    • เวลาบล็อคทั้งหมด ( TBT )
      ตัวชี้วัดที่ช่วยวัดปริมาณ ความรุนแรงของการที่หน้าไม่มีการโต้ตอบ ก่อนที่จะมีการโต้ตอบที่เชื่อถือได้ (นั่นคือ เธรดหลักไม่มีงานใดๆ ที่ทำงานเกิน 50 มิลลิวินาที ( งานยาว ) เป็นเวลาอย่างน้อย 5 วินาที) เมตริกจะวัดระยะเวลาทั้งหมดระหว่างการระบายสีครั้งแรกกับ Time to Interactive (TTI) ที่เธรดหลักถูกบล็อกนานพอที่จะป้องกันการตอบสนองอินพุต ไม่น่าแปลกใจเลยที่ TBT ที่ต่ำเป็นตัวบ่งชี้ที่ดีสำหรับประสิทธิภาพที่ดี (ขอบคุณ อาร์เทม ฟิล)
    • การเปลี่ยนแปลงเค้าโครงสะสม ( CLS )
      เมตริกเน้นว่าผู้ใช้พบ การเปลี่ยนแปลงรูปแบบ ที่ไม่คาดคิดบ่อยเพียงใด ( reflows ) เมื่อเข้าถึงไซต์ โดยจะตรวจสอบองค์ประกอบ ที่ไม่เสถียร และผลกระทบต่อประสบการณ์โดยรวม คะแนนยิ่งน้อยยิ่งดี
    • ดัชนีความเร็ว
      วัดความเร็วที่เนื้อหาของหน้าถูกเติมด้วยสายตา ยิ่งคะแนนต่ำยิ่งดี คะแนนดัชนีความเร็วคำนวณตาม ความเร็วของความคืบหน้าของภาพ แต่เป็นเพียงค่าที่คำนวณได้ นอกจากนี้ยังมีความละเอียดอ่อนต่อขนาดวิวพอร์ต ดังนั้นคุณต้องกำหนดช่วงของการกำหนดค่าการทดสอบที่ตรงกับผู้ชมเป้าหมายของคุณ โปรดทราบว่า LCP มีความสำคัญน้อยลงเมื่อกลายเป็นตัวชี้วัดที่เกี่ยวข้องมากขึ้น ( ขอบคุณ Boris, Artem! )
    • เวลา CPU ที่ใช้ไป
      ตัวชี้วัดที่แสดง ความถี่ และ ระยะเวลา ที่เธรดหลักถูกบล็อก การทำงานกับการวาดภาพ การแสดงผล การเขียนสคริปต์ และการโหลด เวลา CPU ที่สูงเป็นตัวบ่งชี้ที่ชัดเจนของประสบการณ์ที่ แย่ เช่น เมื่อผู้ใช้พบกับความล่าช้าที่เห็นได้ชัดเจนระหว่างการกระทำและการตอบสนอง ด้วย WebPageTest คุณสามารถเลือก "Capture Dev Tools Timeline" บนแท็บ "Chrome" เพื่อแสดงรายละเอียดของเธรดหลักขณะทำงานบนอุปกรณ์ใดๆ ก็ตามที่ใช้ WebPageTest
    • ค่าใช้จ่าย CPU ระดับส่วนประกอบ
      เช่นเดียวกับ เวลา CPU ที่ใช้ ตัววัดนี้เสนอโดย Stoyan Stefanov สำรวจ ผลกระทบของ JavaScript บน CPU แนวคิดคือการใช้จำนวนคำสั่ง CPU ต่อส่วนประกอบเพื่อทำความเข้าใจผลกระทบต่อประสบการณ์โดยรวมโดยแยกส่วน สามารถใช้งานได้โดยใช้ Puppeteer และ Chrome
    • ดัชนีความผิดหวัง
      แม้ว่าเมตริกหลายตัวที่แสดงด้านบนจะอธิบายเมื่อมีเหตุการณ์หนึ่งเกิดขึ้น FrustrationIndex ของ Tim Vereecke จะพิจารณา ช่องว่าง ระหว่างเมตริกแทนที่จะดูทีละรายการ จะพิจารณาเหตุการณ์สำคัญที่ผู้ใช้ปลายทางรับรู้ เช่น มองเห็นชื่อเรื่อง มองเห็นเนื้อหาแรก มองเห็นได้ชัดเจน และหน้าดูพร้อม และคำนวณคะแนนซึ่งระบุระดับความหงุดหงิดขณะโหลดหน้า ยิ่งช่องว่างมากเท่าไร โอกาสที่ผู้ใช้จะหงุดหงิดก็ยิ่งมากขึ้นเท่านั้น อาจเป็น KPI ที่ดีสำหรับประสบการณ์ผู้ใช้ Tim ได้เผยแพร่โพสต์โดยละเอียดเกี่ยวกับ FrustrationIndex และวิธีการทำงาน
    • ผลกระทบของน้ำหนักโฆษณา
      หากไซต์ของคุณขึ้นอยู่กับรายได้ที่เกิดจากการโฆษณา จะเป็นประโยชน์ในการติดตามน้ำหนักของโค้ดที่เกี่ยวข้องกับโฆษณา สคริปต์ของ Paddy Ganti สร้าง URL สองรายการ (หนึ่งรายการปกติและอีกรายการหนึ่งบล็อกโฆษณา) ให้สร้างการเปรียบเทียบวิดีโอผ่าน WebPageTest และรายงานเดลต้า
    • ตัวชี้วัดความเบี่ยงเบน
      ตามที่วิศวกรของ Wikipedia ระบุไว้ ข้อมูล ความแปรปรวน ที่มีอยู่ในผลลัพธ์ของคุณสามารถแจ้งให้คุณทราบว่าเครื่องมือของคุณมีความน่าเชื่อถือเพียงใด และคุณควรให้ความสนใจเท่าใดต่อการเบี่ยงเบนและส่วนนอก ความแปรปรวนมากเป็นตัวบ่งชี้ถึงการปรับเปลี่ยนที่จำเป็นในการตั้งค่า นอกจากนี้ยังช่วยให้เข้าใจว่าบางหน้าวัดได้ยากกว่าหรือไม่ เช่น เนื่องจากสคริปต์ของบุคคลที่สามทำให้เกิดการเปลี่ยนแปลงที่สำคัญ อาจเป็นความคิดที่ดีที่จะติดตามเวอร์ชันของเบราว์เซอร์เพื่อทำความเข้าใจการกระแทกของประสิทธิภาพเมื่อมีการเปิดตัวเบราว์เซอร์เวอร์ชันใหม่
    • เมตริกที่กำหนดเอง
      เมตริกที่กำหนดเองถูกกำหนดโดยความต้องการทางธุรกิจและประสบการณ์ของลูกค้า คุณต้องระบุพิกเซลที่ สำคัญ สคริปต์ ที่สำคัญ CSS ที่จำเป็น และเนื้อหาที่ เกี่ยวข้อง และวัดว่าส่งไปยังผู้ใช้ได้เร็วเพียงใด คุณสามารถตรวจสอบ Hero Rendering Times หรือใช้ Performance API เพื่อทำเครื่องหมายการประทับเวลาเฉพาะสำหรับกิจกรรมที่สำคัญสำหรับธุรกิจของคุณ นอกจากนี้ คุณยังสามารถรวบรวมเมตริกที่กำหนดเองด้วย WebPagetest โดยเรียกใช้ JavaScript ตามอำเภอใจเมื่อสิ้นสุดการทดสอบ

    โปรดทราบว่า First Meaningful Paint (FMP) ไม่ปรากฏในภาพรวมด้านบน ใช้เพื่อให้ข้อมูลเชิงลึกว่าเซิร์ฟเวอร์ส่งออกข้อมูลได้เร็วเพียง ใด โดยทั่วไปแล้ว Long FMP จะระบุว่า JavaScript บล็อกเธรดหลัก แต่อาจเกี่ยวข้องกับปัญหาแบ็คเอนด์/เซิร์ฟเวอร์เช่นกัน อย่างไรก็ตาม เมตริกนี้เลิกใช้งานแล้วเมื่อเร็วๆ นี้ เนื่องจากดูเหมือนว่าจะไม่ถูกต้องในประมาณ 20% ของกรณีทั้งหมด มันถูกแทนที่ด้วย LCP อย่างมีประสิทธิภาพซึ่งมีความน่าเชื่อถือมากกว่าและให้เหตุผลง่ายกว่า ไม่รองรับใน Lighthouse อีกต่อไป ตรวจสอบเมตริกและคำแนะนำประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลางล่าสุดอีกครั้ง เพื่อให้แน่ใจว่าคุณอยู่ในหน้าที่ปลอดภัย ( ขอบคุณ Patrick Meenan )

    Steve Souders มีคำอธิบายโดยละเอียดเกี่ยวกับเมตริกเหล่านี้จำนวนมาก สิ่งสำคัญคือต้องสังเกตว่าแม้ว่า Time-To-Interactive จะถูกวัดโดยการเรียกใช้การตรวจสอบอัตโนมัติใน สภาพแวดล้อมห้องปฏิบัติการ ที่เรียกว่า First Input Delay แสดงถึงประสบการณ์ของผู้ใช้ จริง โดยที่ผู้ใช้ จริง ประสบกับความล่าช้าที่เห็นได้ชัดเจน โดยทั่วไป คุณควรวัดและติดตามทั้งคู่เสมอ

    เมตริกที่ต้องการอาจแตกต่างกันไปตามบริบทของแอปพลิเคชัน เช่น สำหรับ UI ของ Netflix TV การตอบสนองของคีย์ การใช้หน่วยความจำและ TTI มีความสำคัญมากกว่า และสำหรับวิกิพีเดีย การเปลี่ยนแปลงภาพแรก/สุดท้าย และเมตริกเวลาที่ใช้ CPU มีความสำคัญมากกว่า

    หมายเหตุ : ทั้ง FID และ TTI ไม่ได้พิจารณาถึงพฤติกรรมการเลื่อน การเลื่อนสามารถเกิดขึ้นได้เองโดยอิสระ เนื่องจากไม่ใช่เธรดหลัก ดังนั้นสำหรับไซต์การบริโภคเนื้อหาจำนวนมาก เมตริกเหล่านี้อาจมีความสำคัญน้อยกว่ามาก ( ขอบคุณ แพทริค! )

เมตริกประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลางช่วยให้เข้าใจประสบการณ์ของผู้ใช้จริงได้ดีขึ้น
เมตริกประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลางให้ข้อมูลเชิงลึกที่ดีขึ้นเกี่ยวกับประสบการณ์ของผู้ใช้จริง First Input Delay (FID) เป็นตัวชี้วัดใหม่ที่พยายามบรรลุเป้าหมายนั้น (ตัวอย่างขนาดใหญ่)
ใหม่ Core Web Vitals ในภาพรวม, LCP < 2.5s, FID <100ms, CLS < 0.1
Core Web Vitals ใหม่ในภาพรวม, LCP < 2.5s, FID <100ms, CLS < 0.1 (Core Web Vitals ผ่าน Addy Osmani)
  1. วัดผลและเพิ่มประสิทธิภาพ Core Web Vitals
    มาเป็นเวลานาน ตัวชี้วัดประสิทธิภาพค่อนข้างเป็นเทคนิค โดยเน้นที่มุมมองทางวิศวกรรมว่าเซิร์ฟเวอร์ตอบสนองเร็วเพียงใด และเบราว์เซอร์โหลดเร็วเพียงใด ตัวชี้วัดมีการเปลี่ยนแปลงตลอดหลายปีที่ผ่านมา — พยายามหาวิธีที่จะบันทึกประสบการณ์ของผู้ใช้ จริง มากกว่าการกำหนดเวลาของเซิร์ฟเวอร์ ในเดือนพฤษภาคม 2020 Google ได้ประกาศ Core Web Vitals ซึ่งเป็นชุดเมตริกประสิทธิภาพที่เน้นผู้ใช้ใหม่ โดยแต่ละรายการจะนำเสนอแง่มุมที่แตกต่างกันของประสบการณ์ผู้ใช้

    สำหรับแต่ละรายการ Google แนะนำช่วงเป้าหมายความเร็วที่ยอมรับได้ อย่างน้อย 75% ของการดูหน้าเว็บทั้งหมด ควรเกิน ช่วงที่ดี เพื่อผ่านการประเมินนี้ เมตริกเหล่านี้ได้รับความสนใจอย่างรวดเร็ว และเมื่อ Core Web Vitals กลายเป็นสัญญาณการจัดอันดับสำหรับ Google Search ในเดือนพฤษภาคม 2021 ( การอัปเดตอัลกอริธึมการจัดอันดับ Page Experience ) บริษัทหลายแห่งหันความสนใจไปที่คะแนนประสิทธิภาพของตน

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

    • Largest Contentful Paint ( LCP ) < 2.5 วินาที
      วัดการ โหลด หน้า และรายงานเวลาแสดงผลของ รูปภาพหรือบล็อกข้อความที่ใหญ่ที่สุด ที่มองเห็นได้ภายในวิวพอร์ต ดังนั้น LCP ได้รับผลกระทบจากทุกสิ่งที่ขัดขวางการแสดงข้อมูลสำคัญ — ไม่ว่าจะเป็นเวลาตอบสนองของเซิร์ฟเวอร์ที่ช้า, การบล็อก CSS, JavaScript บนเครื่องบิน (บุคคลที่หนึ่งหรือบุคคลที่สาม), การโหลดฟอนต์ของเว็บ, การดำเนินการเรนเดอร์หรือระบายสีที่มีราคาแพง, ขี้เกียจ -โหลดรูปภาพ หน้าจอโครงกระดูก หรือการแสดงผลฝั่งไคลเอ็นต์

      เพื่อประสบการณ์ที่ดี LCP ควรเกิดขึ้น ภายใน 2.5 วินาทีนับ จากที่หน้าเริ่มโหลดครั้งแรก ซึ่งหมายความว่าเราต้องแสดงส่วนแรกที่มองเห็นได้ของหน้าเว็บโดยเร็วที่สุด ซึ่งจะต้องใช้ CSS ที่สำคัญที่ปรับแต่งสำหรับแต่ละเทมเพลต จัดการ <head> -order และดึงเนื้อหาที่สำคัญล่วงหน้า (เราจะพูดถึงในภายหลัง)

      สาเหตุหลักที่ทำให้คะแนน LCP ต่ำมักเกิดจากรูปภาพ ในการส่ง LCP ใน <2.5 วินาทีบน Fast 3G ซึ่งโฮสต์บนเซิร์ฟเวอร์ที่ได้รับการปรับแต่งมาอย่างดี ทั้งหมดเป็นแบบสแตติกโดยไม่มีการเรนเดอร์ฝั่งไคลเอ็นต์และด้วยภาพที่มาจาก CDN อิมเมจเฉพาะ หมายความว่า ขนาดภาพตามทฤษฎีสูงสุดอยู่ที่ประมาณ 144KB เท่านั้น นั่นเป็นสาเหตุที่รูปภาพที่ตอบสนองมีความสำคัญ รวมถึงการโหลดรูปภาพที่สำคัญล่วงหน้าล่วงหน้า (ด้วย preload )

      เคล็ดลับด่วน : หากต้องการทราบสิ่งที่ถือว่าเป็น LCP บนหน้าเว็บ ใน DevTools คุณสามารถวางเมาส์เหนือป้าย LCP ใต้ "การกำหนดเวลา" ในแผงประสิทธิภาพ ( ขอบคุณ Tim Kadec !)

    • First Input Delay ( FID ) < 100ms.
      วัดการ ตอบสนอง ของ UI เช่น ระยะเวลาที่เบราว์เซอร์ยุ่ง กับงานอื่นๆ ก่อนที่มันจะตอบสนองต่อเหตุการณ์การป้อนข้อมูลของผู้ใช้ที่ไม่ต่อเนื่อง เช่น การแตะหรือการคลิก ได้รับการออกแบบมาเพื่อบันทึกความล่าช้าที่เกิดจากเธรดหลักไม่ว่าง โดยเฉพาะอย่างยิ่งในระหว่างการโหลดหน้าเว็บ

      เป้าหมายคืออยู่ภายใน 50-100ms สำหรับทุกการโต้ตอบ ในการไปถึงจุดนั้น เราจำเป็นต้องระบุงานที่ยาว (บล็อกเธรดหลักเป็นเวลา >50 มิลลิวินาที) และแยกส่วน แยกโค้ดเป็นกลุ่มเป็นหลายๆ ชิ้น ลดเวลาดำเนินการ JavaScript เพิ่มประสิทธิภาพการดึงข้อมูล เลื่อนการดำเนินการสคริปต์ของบุคคลที่สาม ย้าย JavaScript ไปยังเธรดพื้นหลังด้วย Web Worker และใช้การไฮเดรชั่นแบบก้าวหน้าเพื่อลดต้นทุนการคืนสภาพใน SPA

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

    • การเปลี่ยนแปลงเค้าโครงสะสม ( CLS ) < 0.1
      วัด ความเสถียรทางสายตา ของ UI เพื่อให้แน่ใจว่ามีการโต้ตอบที่ราบรื่นและเป็นธรรมชาติ กล่าวคือ ผลรวมของคะแนนการเปลี่ยนเลย์เอาต์แต่ละรายการสำหรับการเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดทุกครั้งที่เกิดขึ้นในช่วงอายุของเพจ การเปลี่ยนเลย์เอาต์แต่ละรายการเกิดขึ้นทุกครั้งที่องค์ประกอบที่มองเห็นได้เปลี่ยนตำแหน่งบนเพจ คะแนนขึ้นอยู่กับขนาดของเนื้อหาและระยะทางที่เคลื่อนย้าย

      ดังนั้นทุกครั้งที่มีกะปรากฏขึ้น — เช่น เมื่อฟอนต์สำรองและฟอนต์เว็บมีการวัดฟอนต์ที่แตกต่างกัน หรือโฆษณา การฝัง หรือ iframes มาช้า หรือขนาดรูปภาพ/วิดีโอไม่ได้รับการสงวนไว้ หรือ CSS ที่ล่าช้าในการทาสีใหม่ หรือการเปลี่ยนแปลงถูกแทรกโดย JavaScript ตอนปลาย — มันมีผลกระทบต่อคะแนน CLS ค่าที่แนะนำสำหรับประสบการณ์ที่ดีคือ CLS < 0.1

    เป็นที่น่าสังเกตว่า Core Web Vitals ควรจะพัฒนาเมื่อเวลาผ่านไป ด้วย วัฏจักรรายปีที่คาดการณ์ ได้ สำหรับการอัปเดตในปีแรก เราอาจคาดหวังให้ First Contentful Paint ได้รับการโปรโมตเป็น Core Web Vitals, เกณฑ์ FID ที่ลดลง และการสนับสนุนที่ดีขึ้นสำหรับแอปพลิเคชันหน้าเดียว We might also see the responding to user inputs after load gaining more weight, along with security, privacy and accessibility (!) considerations.

    Related to Core Web Vitals, there are plenty of useful resources and articles that are worth looking into:

    • Web Vitals Leaderboard allows you to compare your scores against competition on mobile, tablet, desktop, and on 3G and 4G.
    • Core SERP Vitals, a Chrome extension that shows the Core Web Vitals from CrUX in the Google Search Results.
    • Layout Shift GIF Generator that visualizes CLS with a simple GIF (also available from the command line).
    • web-vitals library can collect and send Core Web Vitals to Google Analytics, Google Tag Manager or any other analytics endpoint.
    • Analyzing Web Vitals with WebPageTest, in which Patrick Meenan explores how WebPageTest exposes data about Core Web Vitals.
    • Optimizing with Core Web Vitals, a 50-min video with Addy Osmani, in which he highlights how to improve Core Web Vitals in an eCommerce case-study.
    • Cumulative Layout Shift in Practice and Cumulative Layout Shift in the Real World are comprehensive articles by Nic Jansma, which cover pretty much everything about CLS and how it correlates with key metrics such as Bounce Rate, Session Time or Rage Clicks.
    • What Forces Reflow, with an overview of properties or methods, when requested/called in JavaScript, that will trigger the browser to synchronously calculate the style and layout.
    • CSS Triggers shows which CSS properties trigger Layout, Paint and Composite.
    • Fixing Layout Instability is a walkthrough of using WebPageTest to identify and fix layout instability issues.
    • Cumulative Layout Shift, The Layout Instability Metric, another very detailed guide by Boris Schapira on CLS, how it's calcualted, how to measure and how to optimize for it.
    • How To Improve Core Web Vitals, a detailed guide by Simon Hearne on each of the metrics (including other Web Vitals, such as FCP, TTI, TBT), when they occur and how they are measured.

    So, are Core Web Vitals the ultimate metrics to follow ? Not quite. They are indeed exposed in most RUM solutions and platforms already, including Cloudflare, Treo, SpeedCurve, Calibre, WebPageTest (in the filmstrip view already), Newrelic, Shopify, Next.js, all Google tools (PageSpeed Insights, Lighthouse + CI, Search Console etc.) and many others.

    However, as Katie Sylor-Miller explains, some of the main problems with Core Web Vitals are the lack of cross-browser support, we don't really measure the full lifecycle of a user's experience, plus it's difficult to correlate changes in FID and CLS with business outcomes.

    As we should be expecting Core Web Vitals to evolve, it seems only reasonable to always combine Web Vitals with your custom-tailored metrics to get a better understanding of where you stand in terms of performance.

  2. Gather data on a device representative of your audience.
    To gather accurate data, we need to thoroughly choose devices to test on. In most companies, that means looking into analytics and creating user profiles based on most common device types. Yet often, analytics alone doesn't provide a complete picture. A significant portion of the target audience might be abandoning the site (and not returning back) just because their experience is too slow, and their devices are unlikely to show up as the most popular devices in analytics for that reason. So, additionally conducting research on common devices in your target group might be a good idea.

    Globally in 2020, according to the IDC, 84.8% of all shipped mobile phones are Android devices. An average consumer upgrades their phone every 2 years, and in the US phone replacement cycle is 33 months. Average bestselling phones around the world will cost under $200.

    A representative device, then, is an Android device that is at least 24 months old , costing $200 or less, running on slow 3G, 400ms RTT and 400kbps transfer, just to be slightly more pessimistic. This might be very different for your company, of course, but that's a close enough approximation of a majority of customers out there. In fact, it might be a good idea to look into current Amazon Best Sellers for your target market. ( Thanks to Tim Kadlec, Henri Helvetica and Alex Russell for the pointers! ).

    When building a new site or app, always check current Amazon Best Sellers for your target market first
    When building a new site or app, always check current Amazon Best Sellers for your target market first. (ตัวอย่างขนาดใหญ่)

    What test devices to choose then? The ones that fit well with the profile outlined above. It's a good option to choose a slightly older Moto G4/G5 Plus, a mid-range Samsung device (Galaxy A50, S8), a good middle-of-the-road device like a Nexus 5X, Xiaomi Mi A3 or Xiaomi Redmi Note 7 and a slow device like Alcatel 1X or Cubot X19, perhaps in an open device lab. For testing on slower thermal-throttled devices, you could also get a Nexus 4, which costs just around $100.

    Also, check the chipsets used in each device and do not over-represent one chipset : a few generations of Snapdragon and Apple as well as low-end Rockchip, Mediatek would be enough (thanks, Patrick!) .

    If you don't have a device at hand, emulate mobile experience on desktop by testing on a throttled 3G network (eg 300ms RTT, 1.6 Mbps down, 0.8 Mbps up) with a throttled CPU (5× slowdown). Eventually switch over to regular 3G, slow 4G (eg 170ms RTT, 9 Mbps down, 9Mbps up), and Wi-Fi. To make the performance impact more visible, you could even introduce 2G Tuesdays or set up a throttled 3G/4G network in your office for faster testing.

    Keep in mind that on a mobile device, we should be expecting a 4×–5× slowdown compared to desktop machines. Mobile devices have different GPUs, CPU, memory and different battery characteristics. That's why it's important to have a good profile of an average device and always test on such a device.

  3. Introducing the slowest day of the week
    Introducing the slowest day of the week. Facebook has introduced 2G Tuesdays to increase visibility and sensitivity of slow connections. ( Image source)

    Luckily, there are many great options that help you automate the collection of data and measure how your website performs over time according to these metrics. Keep in mind that a good performance picture covers a set of performance metrics, lab data and field data:

    • Synthetic testing tools collect lab data in a reproducible environment with predefined device and network settings (eg Lighthouse , Calibre , WebPageTest ) and
    • Real User Monitoring ( RUM ) tools evaluate user interactions continuously and collect field data (eg SpeedCurve , New Relic — the tools provide synthetic testing, too).

    The former is particularly useful during development as it will help you identify, isolate and fix performance issues while working on the product. The latter is useful for long-term maintenance as it will help you understand your performance bottlenecks as they are happening live — when users actually access the site.

    By tapping into built-in RUM APIs such as Navigation Timing, Resource Timing, Paint Timing, Long Tasks, etc., synthetic testing tools and RUM together provide a complete picture of performance in your application. You could use Calibre, Treo, SpeedCurve, mPulse and Boomerang, Sitespeed.io, which all are great options for performance monitoring. Furthermore, with Server Timing header, you could even monitor back-end and front-end performance all in one place.

    Note : It's always a safer bet to choose network-level throttlers, external to the browser, as, for example, DevTools has issues interacting with HTTP/2 push, due to the way it's implemented ( thanks, Yoav, Patrick !). For Mac OS, we can use Network Link Conditioner, for Windows Windows Traffic Shaper, for Linux netem, and for FreeBSD dummynet.

    As it's likely that you'll be testing in Lighthouse, keep in mind that you can:

    • use Lighthouse CI to track Lighthouse scores over time (it's quite impressive),
    • run Lighthouse in GitHub Actions to get a Lighthouse report alongside every PR,
    • run a Lighthouse performance audit on every page of a site (via Lightouse Parade), with an output saved as CSV,
    • use Lighthouse Scores Calculator and Lighthouse metric weights if you need to dive into more detail.
    • Lighthouse is available for Firefox as well, but under the hood it uses the PageSpeed Insights API and generates a report based on a headless Chrome 79 User-Agent.
Lighthouse CI is quite remarkable: a suite of tools to continuously run, save, retrieve, and assert against Lighthouse results
Lighthouse CI is quite remarkable: a suite of tools to continuously run, save, retrieve, and assert against Lighthouse results. (ตัวอย่างขนาดใหญ่)
  1. Set up "clean" and "customer" profiles for testing.
    While running tests in passive monitoring tools, it's a common strategy to turn off anti-virus and background CPU tasks, remove background bandwidth transfers and test with a clean user profile without browser extensions to avoid skewed results (in Firefox, and in Chrome).
    DebugBear's report highlights 20 slowest extensions, including password managers, ad-blockers and popular applications like Evernote and Grammarly
    DebugBear's report highlights 20 slowest extensions, including password managers, ad-blockers and popular applications like Evernote and Grammarly. (ตัวอย่างขนาดใหญ่)

    However, it's also a good idea to study which browser extensions your customers use frequently, and test with dedicated "customer" profiles as well. In fact, some extensions might have a profound performance impact (2020 Chrome Extension Performance Report) on your application, and if your users use them a lot, you might want to account for it up front. Hence, "clean" profile results alone are overly optimistic and can be crushed in real-life scenarios.

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

การตั้งเป้าหมายที่สมจริง

  1. เวลาตอบสนอง 100 มิลลิวินาที 60 fps
    เพื่อให้การโต้ตอบเป็นไปอย่างราบรื่น อินเทอร์เฟซมี 100 มิลลิวินาทีเพื่อตอบสนองต่ออินพุตของผู้ใช้ นานกว่านั้น และผู้ใช้มองว่าแอปมีความล่าช้า RAIL ซึ่งเป็นโมเดลประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลางให้ เป้าหมายที่ดี แก่คุณ : เพื่อให้มีการตอบสนอง <100 มิลลิวินาที หน้าต้องให้การควบคุมกลับไปที่เธรดหลักอย่างช้าที่สุดทุกๆ <50 มิลลิวินาที เวลาแฝงของอินพุตโดยประมาณจะบอกเราว่าเรากำลังแตะถึงเกณฑ์นั้นหรือไม่ และในอุดมคติแล้ว ค่าเวลาแฝงของอินพุตควรต่ำกว่า 50 มิลลิวินาที สำหรับจุดที่มีความกดดันสูง เช่น แอนิเมชั่น เป็นการดีที่สุดที่จะไม่ทำอะไรอย่างอื่นที่คุณสามารถทำได้และขั้นต่ำสุดที่คุณไม่สามารถทำได้

    RAIL โมเดลประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลาง
    RAIL โมเดลประสิทธิภาพที่เน้นผู้ใช้เป็นศูนย์กลาง

    นอกจากนี้ แต่ละเฟรมของแอนิเมชั่นควรทำให้เสร็จภายในเวลาน้อยกว่า 16 มิลลิวินาที ดังนั้นจึงบรรลุ 60 เฟรมต่อวินาที (1 วินาที ÷ 60 = 16.6 มิลลิวินาที) — โดยควรน้อยกว่า 10 มิลลิวินาที เนื่องจากเบราว์เซอร์ต้องใช้เวลาในการวาดภาพเฟรมใหม่ลงบนหน้าจอ โค้ดของคุณควรดำเนินการให้เสร็จสิ้นก่อนที่จะกดปุ่ม 16.6 มิลลิวินาที เรากำลังเริ่มพูดคุยเกี่ยวกับ 120fps (เช่น หน้าจอของ iPad Pro ทำงานที่ 120Hz) และ Surma ได้กล่าวถึงโซลูชันประสิทธิภาพการเรนเดอร์บางตัวสำหรับ 120fps แต่ นั่นอาจไม่ใช่เป้าหมายที่เรากำลังดูอยู่

    มองโลกในแง่ร้ายในความคาดหวังด้านประสิทธิภาพ แต่จงมองโลกในแง่ดีในการออกแบบอินเทอร์เฟซและใช้เวลาว่างอย่างชาญฉลาด เห็นได้ชัดว่าเป้าหมายเหล่านี้ใช้กับประสิทธิภาพรันไทม์มากกว่าประสิทธิภาพการโหลด

  2. FID < 100ms, LCP < 2.5s, TTI < 5s บน 3G, งบประมาณขนาดไฟล์ที่สำคัญ < 170KB (gzipped)
    แม้ว่าจะทำได้ยากมาก แต่เป้าหมายสูงสุดที่ดีคือ Time to Interactive ที่อายุต่ำกว่า 5 ปี และสำหรับการเข้าชมซ้ำ ให้ตั้งเป้าไว้สำหรับอายุต่ำกว่า 2 ปี (ทำได้เฉพาะกับพนักงานบริการ) มุ่งสู่การ ระบายสีเนื้อหาที่ใหญ่ที่สุดที่ อายุต่ำกว่า 2.5 วินาที และลด เวลาในการบล็อกโดยรวม และ การเปลี่ยนเค้าโครงสะสม First Input Delay ที่ยอมรับได้คือต่ำกว่า 100ms–70ms ตามที่กล่าวไว้ข้างต้น เรากำลังพิจารณาพื้นฐานว่าเป็นโทรศัพท์ Android มูลค่า 200 ดอลลาร์ (เช่น Moto G4) บนเครือข่าย 3G ที่ช้า โดยจำลองที่ 400ms RTT และความเร็วในการโอน 400kbps

    เรามีข้อจำกัดหลักสองประการที่กำหนดเป้าหมาย ได้ อย่างมีประสิทธิภาพสำหรับการจัดส่งเนื้อหาบนเว็บอย่างรวดเร็ว ในอีกด้านหนึ่ง เรามี ข้อจำกัดในการจัดส่งเครือข่าย เนื่องจาก TCP Slow Start 14KB แรกของ HTML — 10 TCP แพ็กเก็ต แต่ละ 1,460 ไบต์ ได้ประมาณ 14.25 KB แม้ว่าจะไม่ถูกแปลตามตัวอักษรก็ตาม — เป็นส่วนของเพย์โหลดที่สำคัญที่สุด และเป็นเพียงส่วนหนึ่งของงบประมาณที่สามารถจัดส่งในการไปกลับครั้งแรก ( นั่นคือทั้งหมดที่คุณได้รับใน 1 วินาทีที่ 400ms RTT เนื่องจากเวลาปลุกมือถือ)

    เครือข่ายเบราว์เซอร์ประสิทธิภาพสูงโดย Ilya Grigorik
    ด้วยการเชื่อมต่อ TCP เราเริ่มต้นด้วยหน้าต่างความแออัดขนาดเล็กและเพิ่มเป็นสองเท่าสำหรับทุกการไปกลับ ในการไปกลับครั้งแรก เราใส่ได้ 14 KB จาก: ระบบเครือข่ายเบราว์เซอร์ประสิทธิภาพสูงโดย Ilya Grigorik (ตัวอย่างขนาดใหญ่)

    ( หมายเหตุ : เนื่องจากโดยทั่วไป TCP ใช้การเชื่อมต่อเครือข่ายต่ำเกินไป Google ได้พัฒนา TCP Bottleneck Bandwidth และ RRT ( BBR ) ซึ่งเป็นอัลกอริธึมการควบคุมการไหลของ TCP ที่ควบคุมความล่าช้าของ TCP ออกแบบมาสำหรับเว็บสมัยใหม่ มันตอบสนองต่อความแออัดจริง แทนที่จะสูญเสียแพ็กเก็ตเหมือน TCP มันเร็วกว่าอย่างเห็นได้ชัดด้วยปริมาณงานที่สูงขึ้นและเวลาแฝงที่ต่ำกว่า - และอัลกอริทึมทำงานแตกต่างกัน ( ขอบคุณ Victor, Barry! )

    ในทางกลับกัน เรามี ข้อจำกัดด้านฮาร์ดแวร์ ในหน่วยความจำและ CPU เนื่องจากการแยกวิเคราะห์ JavaScript และเวลาในการดำเนินการ (เราจะพูดถึงรายละเอียดในภายหลัง) เพื่อให้บรรลุเป้าหมายที่ระบุไว้ในย่อหน้าแรก เราต้องพิจารณางบประมาณขนาดไฟล์ที่สำคัญสำหรับ JavaScript ความคิดเห็นแตกต่างกันไปตามงบประมาณที่ควรจะเป็น (และขึ้นอยู่กับธรรมชาติของโครงการของคุณเป็นอย่างมาก) แต่งบประมาณ 170KB JavaScript gzipped แล้วจะใช้เวลาถึง 1 วินาทีในการแยกวิเคราะห์และคอมไพล์บนโทรศัพท์ระดับกลาง สมมติว่า 170KB ขยายเป็น 3 เท่าเมื่อคลายการบีบอัด (0.7MB) ซึ่งอาจเป็นเสียงตายของประสบการณ์ผู้ใช้ที่ "ดี" ใน Moto G4 / G5 Plus

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

    หากคุณต้องการกำหนดเป้าหมายไปยังตลาดที่กำลังเติบโต เช่น เอเชียตะวันออกเฉียงใต้ แอฟริกา หรืออินเดีย คุณจะต้องพิจารณาถึงข้อจำกัดที่แตกต่างกันมาก Addy Osmani ครอบคลุมข้อจำกัดหลักๆ ของฟีเจอร์โฟน เช่น อุปกรณ์ราคาถูกและคุณภาพสูงเพียงไม่กี่ตัว เครือข่ายคุณภาพสูงที่ขาดไม่ได้และข้อมูลมือถือราคาแพง — พร้อมด้วย งบประมาณ PRPL-30 และแนวทางการพัฒนาสำหรับสภาพแวดล้อมเหล่านี้

    จากข้อมูลของ Addy Osmani ขนาดที่แนะนำสำหรับเส้นทางที่โหลดแบบ Lazy Loading ก็น้อยกว่า 35 KB . เช่นกัน
    จากข้อมูลของ Addy Osmani ขนาดที่แนะนำสำหรับเส้นทางที่โหลดแบบ Lazy Loading ก็น้อยกว่า 35 KB เช่นกัน (ตัวอย่างขนาดใหญ่)
    Addy Osmani แนะนำงบประมาณประสิทธิภาพ PRPL-30 (30KB gzipped + บันเดิลเริ่มต้นที่ย่อเล็กสุด) หากกำหนดเป้าหมายไปที่ฟีเจอร์โฟน
    Addy Osmani แนะนำงบประมาณประสิทธิภาพ PRPL-30 (30KB gzipped + บันเดิลเริ่มต้นที่ย่อเล็กสุด) หากกำหนดเป้าหมายไปที่ฟีเจอร์โฟน (ตัวอย่างขนาดใหญ่)

    อันที่จริง Alex Russell ของ Google แนะนำให้ตั้งเป้าไว้ที่ 130–170KB gzipped เป็นขอบเขตบนที่สมเหตุสมผล ในสถานการณ์จริง ผลิตภัณฑ์ส่วนใหญ่ไม่ได้ใกล้เคียงกันเลย: ขนาดมัดเฉลี่ยวันนี้อยู่ที่ประมาณ 452 KB ซึ่งเพิ่มขึ้น 53.6% เมื่อเทียบกับต้นปี 2015 บนอุปกรณ์เคลื่อนที่ระดับกลาง เวลา 12–20 วินาทีสำหรับ เวลา -To-โต้ตอบ

    เกณฑ์มาตรฐานประสิทธิภาพของ CPU Geekbench สำหรับสมาร์ทโฟนที่มียอดขายสูงสุดทั่วโลกในปี 2019 JavaScript เน้นย้ำถึงประสิทธิภาพแบบ single-core และถูกผูกมัดกับ CPU
    เกณฑ์มาตรฐานประสิทธิภาพของ CPU ของ Geekbench สำหรับสมาร์ทโฟนที่มียอดขายสูงสุดทั่วโลกในปี 2019 JavaScript เน้นย้ำถึงประสิทธิภาพแบบ single-core (โปรดจำไว้ว่ามันเป็น single-threaded มากกว่าส่วนอื่นๆ ของแพลตฟอร์มเว็บ) และมีการผูกมัดกับ CPU จากบทความของ Addy “การโหลดหน้าเว็บอย่างรวดเร็วด้วยฟีเจอร์โฟนราคา $20” (ตัวอย่างขนาดใหญ่)

    เราสามารถไปได้ไกลกว่างบประมาณขนาดมัด ตัวอย่างเช่น เราสามารถกำหนดงบประมาณประสิทธิภาพตามกิจกรรมของเธรดหลักของเบราว์เซอร์ เช่น เวลาในการระบายสีก่อนเริ่มการเรนเดอร์ หรือติดตามส่วนหน้าของ CPU hogs เครื่องมือต่างๆ เช่น Calibre, SpeedCurve และ Bundlesize สามารถช่วยให้คุณควบคุมงบประมาณได้ และสามารถรวมเข้ากับกระบวนการสร้างของคุณได้

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

    หมายเหตุ : อาจฟังดูแปลกที่จะกำหนดงบประมาณที่เข้มงวดในช่วงเวลาของ HTTP/2 ที่แพร่หลาย 5G และ HTTP/3 ที่กำลังจะมีขึ้น โทรศัพท์มือถือที่พัฒนาอย่างรวดเร็ว และ SPA ที่กำลังเฟื่องฟู อย่างไรก็ตาม สิ่งเหล่านี้ฟังดูสมเหตุสมผลเมื่อเราจัดการกับธรรมชาติของเครือข่ายและฮาร์ดแวร์ที่คาดเดาไม่ได้ รวมถึงทุกอย่างตั้งแต่เครือข่ายที่แออัดไปจนถึงโครงสร้างพื้นฐานที่พัฒนาอย่างช้าๆ ไปจนถึงดาต้าแคป พร็อกซีเบราว์เซอร์ โหมดบันทึกข้อมูล และค่าบริการโรมมิ่งแอบแฝง

จาก 'Fast By Default: Modern Loading Best Practices' โดย Addy Osmani
จาก Fast By Default: แนวทางปฏิบัติที่ดีที่สุดในการโหลดสมัยใหม่โดย Addy Osmani (สไลด์ 19)
งบประมาณด้านประสิทธิภาพควรปรับตามเงื่อนไขเครือข่ายสำหรับอุปกรณ์เคลื่อนที่โดยเฉลี่ย
งบประมาณด้านประสิทธิภาพควรปรับตามเงื่อนไขเครือข่ายสำหรับอุปกรณ์เคลื่อนที่โดยเฉลี่ย (ที่มาของรูปภาพ: Katie Hempenius) (ตัวอย่างขนาดใหญ่)

การกำหนดสภาพแวดล้อม

  1. เลือกและตั้งค่าเครื่องมือสร้างของคุณ
    อย่าไปสนใจมากเกินไปกับสิ่งที่ควรจะเจ๋งในทุกวันนี้ ยึดติดกับสภาพแวดล้อมของคุณในการสร้าง ไม่ว่าจะเป็น Grunt, Gulp, Webpack, Parcel หรือชุดเครื่องมือต่างๆ ตราบใดที่คุณได้รับผลลัพธ์ที่ต้องการ และคุณไม่มีปัญหาในการรักษากระบวนการสร้างของคุณ แสดงว่าคุณทำได้ดี

    ในบรรดาเครื่องมือสร้าง Rollup ยังคงได้รับแรงฉุดลาก Snowpack ก็เช่นกัน แต่ดูเหมือนว่า Webpack จะเป็นเครื่องมือที่ได้รับการยอมรับมากที่สุด โดยมีปลั๊กอินหลายร้อยตัวที่พร้อมใช้งานเพื่อปรับขนาดของงานสร้างของคุณให้เหมาะสมที่สุด ระวัง Webpack Roadmap 2021

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

    เพื่อลดโค้ดที่ซ้ำกันในโครงการ Webpack เราสามารถใช้การแบ่งแบบละเอียด เปิดใช้งานใน Next.js และ Gatsby โดยค่าเริ่มต้น
    เพื่อลดโค้ดที่ซ้ำกันในโปรเจ็กต์ Webpack เราสามารถใช้การแบ่งแบบละเอียด ซึ่งเปิดใช้งานใน Next.js และ Gatsby โดยค่าเริ่มต้น เครดิตภาพ: Addy Osmani (ตัวอย่างขนาดใหญ่)

    ด้วย SplitChunksPlugin ชิ้นส่วนที่แยกออกมาจำนวนมากจะถูกสร้างขึ้นโดยขึ้นอยู่กับเงื่อนไขจำนวนหนึ่ง เพื่อป้องกันการดึงรหัสที่ซ้ำกันในหลายเส้นทาง วิธีนี้ช่วยปรับปรุงเวลาในการโหลดเพจและการแคชระหว่างการนำทาง จัดส่งใน Next.js 9.2 และใน Gatsby v2.20.7

    การเริ่มต้นใช้งาน Webpack อาจเป็นเรื่องยาก ดังนั้นหากคุณต้องการดำดิ่งสู่ Webpack มีแหล่งข้อมูลดีๆ มากมาย:

    • เอกสารประกอบของ Webpack — แน่นอน — เป็นจุดเริ่มต้นที่ดี และ Webpack ก็เช่นกัน — The Confusing Bits โดย Raja Rao และ Annotated Webpack Config โดย Andrew Welch
    • Sean Larkin มีหลักสูตรฟรีบน Webpack: The Core Concepts และ Jeffrey Way ได้เปิดตัวหลักสูตรฟรีที่ยอดเยี่ยมบน Webpack สำหรับทุกคน ทั้งคู่เป็นการแนะนำที่ดีสำหรับการดำน้ำใน Webpack
    • Webpack Fundamentals เป็นหลักสูตร 4 ชั่วโมงที่ครอบคลุมมากกับ Sean Larkin ซึ่งเผยแพร่โดย FrontendMasters
    • ตัวอย่าง Webpack มีการกำหนดค่า Webpack ที่พร้อมใช้งานหลายร้อยรายการ โดยจัดหมวดหมู่ตามหัวข้อและวัตถุประสงค์ โบนัส: นอกจากนี้ยังมีตัวกำหนดค่า Webpack ที่สร้างไฟล์การกำหนดค่าพื้นฐาน
    • Awesome-webpack เป็นรายการทรัพยากร ไลบรารีและเครื่องมือของ Webpack ที่คัดสรรมาเป็นอย่างดี ซึ่งรวมถึงบทความ วิดีโอ หลักสูตร หนังสือ และตัวอย่างสำหรับโปรเจ็กต์ Angular, React และ framework-agnostic
    • เส้นทางสู่การสร้างเนื้อหาการผลิตที่รวดเร็วด้วย Webpack เป็นกรณีศึกษาของ Etsy เกี่ยวกับวิธีที่ทีมเปลี่ยนจากการใช้ระบบบิลด์ JavaScript แบบ RequireJS ไปเป็นการใช้ Webpack และวิธีที่พวกเขาเพิ่มประสิทธิภาพบิลด์ของพวกเขา จัดการเนื้อหามากกว่า 13,200 รายการใน 4 นาที โดยเฉลี่ย
    • เคล็ดลับประสิทธิภาพ Webpack เป็นเธรดเหมืองทองโดย Ivan Akulov ซึ่งมีเคล็ดลับที่เน้นประสิทธิภาพมากมาย รวมถึงคำแนะนำที่เน้นเฉพาะใน Webpack
    • Awesome-webpack-perf เป็น goldmine GitHub repo พร้อมเครื่องมือและปลั๊กอิน Webpack ที่มีประโยชน์สำหรับประสิทธิภาพ ยังดูแลโดย Ivan Akulov
การแสดงภาพการเดินทางของ Etsy สู่งานสร้างการผลิตที่รวดเร็วด้วย Webpack
การเดินทางของ Etsy สู่งานสร้างที่รวดเร็วด้วย Webpack (ผ่าน Addy Osmani) (ตัวอย่างขนาดใหญ่)
  1. ใช้การเพิ่มประสิทธิภาพแบบก้าวหน้าเป็นค่าเริ่มต้น
    อย่างไรก็ตาม หลังจากหลายปีมานี้ การรักษาการเพิ่มประสิทธิภาพแบบก้าวหน้าตามหลักการชี้นำของสถาปัตยกรรมส่วนหน้าและการปรับใช้ของคุณถือเป็นทางออกที่ปลอดภัย ออกแบบและสร้างประสบการณ์หลักก่อน จากนั้นจึงปรับปรุงประสบการณ์ด้วยคุณสมบัติขั้นสูงสำหรับเบราว์เซอร์ที่มีความสามารถ สร้างประสบการณ์ที่ยืดหยุ่น หากเว็บไซต์ของคุณทำงานเร็วบนเครื่องที่ช้าซึ่งมีหน้าจอไม่ดีในเบราว์เซอร์ที่ไม่ดีบนเครือข่ายรองที่เหมาะสม มันจะทำงานเร็วขึ้นในเครื่องที่เร็วซึ่งมีเบราว์เซอร์ที่ดีในเครือข่ายที่เหมาะสมเท่านั้น

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

  2. เลือกพื้นฐานประสิทธิภาพที่แข็งแกร่ง
    ด้วยข้อมูลที่ไม่ทราบจำนวนมากที่ส่งผลกระทบต่อการโหลด — เครือข่าย, การควบคุมปริมาณความร้อน, การกำจัดแคช, สคริปต์ของบริษัทอื่น, รูปแบบการบล็อกพาร์เซอร์, ดิสก์ I/O, เวลาแฝงของ IPC, ส่วนขยายที่ติดตั้ง, ซอฟต์แวร์ป้องกันไวรัสและไฟร์วอลล์, งาน CPU พื้นหลัง, ข้อจำกัดด้านฮาร์ดแวร์และหน่วยความจำ ความแตกต่างในการแคช L2/L3, RTTS — JavaScript มีค่าใช้จ่ายด้านประสบการณ์ที่หนักที่สุด ถัดจากการบล็อกแบบอักษรเว็บที่แสดงผลตามค่าเริ่มต้น และรูปภาพมักใช้หน่วยความจำมากเกินไป ด้วยปัญหาคอขวดด้านประสิทธิภาพที่เคลื่อนออกจากเซิร์ฟเวอร์ไปยังไคลเอนต์ ในฐานะนักพัฒนา เราต้องพิจารณาสิ่งที่ไม่รู้จักเหล่านี้อย่างละเอียดมากขึ้น

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

    Tim Kadlec ได้ทำการวิจัยที่ยอดเยี่ยมเกี่ยวกับประสิทธิภาพของเฟรมเวิร์กสมัยใหม่ และสรุปไว้ในบทความ "JavaScript frameworks มีต้นทุน" เรามักพูดถึงผลกระทบของเฟรมเวิร์กแบบสแตนด์อโลน แต่ในทางปฏิบัติ Tim ได้บันทึกไว้ ไม่ใช่เรื่องแปลกที่จะมี การใช้งานหลายเฟรมเวิ ร์ก บางที jQuery เวอร์ชันเก่าซึ่งกำลังถูกโยกย้ายอย่างช้าๆ ไปสู่เฟรมเวิร์กที่ทันสมัย ​​พร้อมด้วยแอปพลิเคชันรุ่นเก่าบางตัวที่ใช้ Angular เวอร์ชันเก่ากว่า ดังนั้นจึงสมเหตุสมผลกว่าที่จะสำรวจ ต้นทุนสะสม ของไบต์ JavaScript และเวลาดำเนินการของ CPU ที่สามารถทำให้ประสบการณ์ของผู้ใช้แทบจะใช้งานได้แม้ในอุปกรณ์ระดับไฮเอนด์

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

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

ต้นทุนของเฟรมเวิร์ก, เวลา CPU JavaScript: ไซต์ SPA ทำงานได้ไม่ดี
ค่าใช้จ่ายของเฟรมเวิร์ก JavaScript บาย: ไซต์ SPA (ยังคง) ทำงานได้ไม่ดี
เวลา CPU ที่เกี่ยวข้องกับสคริปต์สำหรับอุปกรณ์มือถือและไบต์ JavaScript สำหรับอุปกรณ์ desktopv โดยทั่วไปแล้ว ไซต์ที่มี React หรือ Angular ใช้เวลากับ CPU มากกว่าไซต์อื่นๆ แต่มันขึ้นอยู่กับว่าคุณสร้างไซต์อย่างไร การวิจัยโดยทิม Kadlec (ตัวอย่างขนาดใหญ่)
  1. ประเมินกรอบงานและการพึ่งพา
    ไม่ใช่ทุกโครงการที่ต้องการกรอบงาน และไม่ใช่ทุกหน้าของแอปพลิเคชันหน้าเดียวจำเป็นต้องโหลดกรอบงาน ในกรณีของ Netflix "การนำ React ออก หลายไลบรารีและโค้ดแอปที่เกี่ยวข้องจากฝั่งไคลเอ็นต์ทำให้จำนวน JavaScript ทั้งหมดลดลงกว่า 200KB ส่งผลให้ Time-to-Interactivity ของ Netflix สำหรับหน้าแรกที่ออกจากระบบลดลงมากกว่า 50% ." จากนั้นทีมงานใช้เวลาที่ผู้ใช้ใช้ในหน้า Landing Page เพื่อดึงข้อมูล React ล่วงหน้าสำหรับหน้าถัดไปที่ผู้ใช้น่าจะไปถึง (อ่านต่อเพื่อดูรายละเอียด)

    แล้วถ้าคุณเอาเฟรมเวิร์กที่มีอยู่ออกจากเพจที่สำคัญทั้งหมดล่ะ ด้วย Gatsby คุณสามารถตรวจสอบ gatsby-plugin-no-javascript ที่ลบไฟล์ JavaScript ทั้งหมดที่สร้างโดย Gatsby ออกจากไฟล์ HTML แบบคงที่ บน Vercel คุณยังสามารถอนุญาตให้ปิดการใช้งานรันไทม์ JavaScript ในการผลิตสำหรับบางหน้า (ทดลอง)

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

    ข้อมูลแสดงให้เห็นว่า ตามค่าเริ่มต้น เฟรมเวิร์กมีราคาค่อนข้างแพง: 58.6% ของหน้า React จัดส่ง JavaScript มากกว่า 1 MB และ 36% ของการโหลดหน้า Vue.js มี First Contentful Paint ที่ <1.5 วินาที จากการศึกษาของ Ankur Sethi "แอปพลิเคชัน React ของคุณ จะไม่มีวันโหลดได้เร็วกว่าประมาณ 1.1 วินาที บนโทรศัพท์ทั่วไปในอินเดีย ไม่ว่าคุณจะปรับให้เหมาะสมมากแค่ไหนก็ตาม แอป Angular ของคุณจะใช้เวลาบูตอย่างน้อย 2.7 วินาทีเสมอ ผู้ใช้แอป Vue ของคุณจะต้องรออย่างน้อย 1 วินาทีก่อนที่จะเริ่มใช้งานได้" คุณอาจไม่ได้กำหนดเป้าหมายอินเดียเป็นตลาดหลักของคุณอยู่แล้ว แต่ผู้ใช้ที่เข้าถึงไซต์ของคุณด้วยเงื่อนไขเครือข่ายที่ไม่เหมาะสมจะมีประสบการณ์ที่เปรียบเทียบได้

    แน่นอน เป็น ไปได้ที่จะทำให้ SPA ทำงานได้อย่างรวดเร็ว แต่ก็ไม่ได้ทำได้อย่างรวดเร็วด้วยเหตุนี้ เราจึงต้องคำนึงถึงเวลาและความพยายามที่จำเป็นในการ สร้าง และ รักษา ไว้อย่างรวดเร็ว มันอาจจะง่ายกว่าด้วยการเลือกต้นทุนประสิทธิภาพพื้นฐานที่เบาแต่เนิ่นๆ

    แล้วเราจะเลือก framework อย่างไร ? เป็นความคิดที่ดีที่จะพิจารณา อย่างน้อย ต้นทุนรวมของขนาด + เวลาดำเนินการเริ่มต้นก่อนที่จะเลือกตัวเลือก ตัวเลือกน้ำหนักเบา เช่น Preact, Inferno, Vue, Svelte, Alpine หรือ Polymer สามารถทำงานให้เสร็จลุล่วงได้ด้วยดี ขนาดของเส้นฐานของคุณจะกำหนดข้อจำกัดสำหรับโค้ดของแอปพลิเคชันของคุณ

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

    คุณสามารถประเมินผู้สมัครของคุณ (หรือไลบรารี JavaScript โดยทั่วไป) เกี่ยวกับระบบการให้คะแนนแบบสเกล 12 จุดของ Sacha Greif โดยการสำรวจคุณลักษณะ การเข้าถึง ความเสถียร ประสิทธิภาพ แพ็คเกจระบบนิเวศ ชุมชน เส้นโค้งการเรียนรู้ เอกสารประกอบ เครื่องมือ บันทึกการติดตาม , ทีมงาน , ความเข้ากันได้ , ความปลอดภัย เป็นต้น

    Perf Track ติดตามประสิทธิภาพของเฟรมเวิร์กตามขนาดที่ต้องการ
    Perf Track ติดตามประสิทธิภาพของเฟรมเวิร์กตามขนาด (ตัวอย่างขนาดใหญ่)

    คุณยังสามารถพึ่งพาข้อมูลที่รวบรวมบนเว็บได้ในระยะเวลานานอีกด้วย ตัวอย่างเช่น Perf Track ติดตามประสิทธิภาพของเฟรมเวิร์กตามขนาด โดยแสดงคะแนน Core Web Vitals ที่รวมต้นทางสำหรับเว็บไซต์ที่สร้างใน Angular, React, Vue, Polymer, Preact, Ember, Svelte และ AMP คุณยังสามารถระบุและเปรียบเทียบเว็บไซต์ที่สร้างด้วย Gatsby, Next.js หรือ Create React App ตลอดจนเว็บไซต์ที่สร้างด้วย Nuxt.js (Vue) หรือ Sapper (Svelte)

    จุดเริ่มต้นที่ดีคือการเลือก สแต็กเริ่มต้นที่ดี สำหรับแอปพลิเคชันของคุณ Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI และ PWA Starter Kit ให้ค่าเริ่มต้นที่สมเหตุสมผลสำหรับการโหลดอย่างรวดเร็วจากกล่องบนฮาร์ดแวร์มือถือโดยเฉลี่ย ​​ดูคำแนะนำด้านประสิทธิภาพการทำงานเฉพาะเฟรมเวิร์กของ web.dev สำหรับ React และ Angular ( ขอบคุณ Phillip! )

    และบางทีคุณอาจใช้แนวทางที่สดชื่นกว่านี้เล็กน้อยเพื่อสร้างแอปพลิเคชันแบบหน้าเดียวทั้งหมด — Turbolinks ไลบรารี JavaScript ขนาด 15KB ที่ใช้ HTML แทน JSON เพื่อแสดงมุมมอง ดังนั้นเมื่อคุณคลิกลิงก์ Turbolinks จะดึงหน้าโดยอัตโนมัติ สลับใน <body> และรวม <head> เข้าด้วยกัน โดยไม่เสียค่าใช้จ่ายในการโหลดหน้าเว็บแบบเต็ม คุณสามารถตรวจสอบรายละเอียดโดยย่อและเอกสารประกอบฉบับสมบูรณ์เกี่ยวกับสแตก (Hotwire)

กราฟคล้ายฮิสโตแกรมแสดงประสิทธิภาพการประมวลผลของโทรศัพท์ที่มียอดขายสูงสุด
CPU และประสิทธิภาพการประมวลผลของโทรศัพท์ที่มียอดขายสูงสุด (เครดิตรูปภาพ: Addy Osmani) (ตัวอย่างขนาดใหญ่)
  1. การแสดงผลฝั่งไคลเอ็นต์หรือการแสดงผลฝั่งเซิร์ฟเวอร์? ทั้งคู่!
    นั่นเป็นการสนทนาที่ค่อนข้างดุเดือด แนวทางที่ดีที่สุดคือการตั้งค่าการบูทแบบโปรเกรสซีฟ: ใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์เพื่อรับ First Contenful Paint อย่างรวดเร็ว แต่ยังรวมถึง JavaScript ที่จำเป็นน้อยที่สุดเพื่อให้เวลาในการโต้ตอบใกล้เคียงกับ First Contentful Paint หาก JavaScript มาช้าเกินไปหลังจาก FCP เบราว์เซอร์จะล็อกเธรดหลักในขณะที่แยกวิเคราะห์ รวบรวม และดำเนินการ JavaScript ที่ค้นพบในช่วงปลาย ดังนั้นจึงเป็นการใส่กุญแจมือการโต้ตอบของไซต์หรือแอปพลิเคชัน

    เพื่อหลีกเลี่ยงปัญหานี้ ให้ แยกการทำงาน ของฟังก์ชันออกเป็นงานแบบอะซิงโครนัสที่แยกจากกัน และถ้าเป็นไปได้ให้ใช้ requestIdleCallback พิจารณาการโหลดส่วน UI แบบ Lazy Loading โดยใช้การรองรับ Dynamic import() ของ WebPack หลีกเลี่ยงการโหลด แยกวิเคราะห์ และคอมไพล์ค่าใช้จ่ายจนกว่าผู้ใช้จะต้องการมันจริงๆ ( ขอบคุณ Addy! )

    ดังที่กล่าวไว้ข้างต้น Time to Interactive (TTI) จะบอกเราเวลาระหว่างการนำทางและการโต้ตอบ ในรายละเอียด ตัวชี้วัดถูกกำหนดโดยดูที่หน้าต่างห้าวินาทีแรกหลังจากแสดงเนื้อหาเริ่มต้น ซึ่งไม่มีงาน JavaScript ใดใช้เวลา นานกว่า 50 มิลลิวินาที ( งานยาว ) หากงานเกิน 50ms เกิดขึ้น การค้นหาหน้าต่างห้าวินาทีจะเริ่มต้นใหม่ ด้วยเหตุนี้ เบราว์เซอร์จะถือว่าก่อนถึง Interactive เพียงเพื่อเปลี่ยนเป็น Frozen เพียงเพื่อเปลี่ยนกลับเป็น Interactive ในที่สุด

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

    ถึงกระนั้นเราก็ไปถึงที่นั่น วันนี้มีทางเลือกสองสามทางที่เราสามารถสำรวจได้ และ Houssein Djirdeh และ Jason Miller ให้ภาพรวมที่ยอดเยี่ยมของตัวเลือกเหล่านี้ในการพูดคุยของพวกเขาเกี่ยวกับ Rendering on the Web และบทความของ Jason และ Addy เกี่ยวกับ Modern Front-End Architectures ภาพรวมด้านล่างอิงจากผลงานอันโดดเด่นของพวกเขา

    • การแสดงผลฝั่งเซิร์ฟเวอร์แบบเต็ม (SSR)
      ใน SSR แบบคลาสสิก เช่น WordPress คำขอทั้งหมดจะได้รับการจัดการบนเซิร์ฟเวอร์ทั้งหมด เนื้อหาที่ร้องขอจะถูกส่งกลับเป็นหน้า HTML ที่เสร็จสิ้น และเบราว์เซอร์สามารถแสดงผลได้ทันที ดังนั้น แอป SSR จึงไม่สามารถใช้ DOM API ได้จริงๆ ช่องว่างระหว่าง First Contentful Paint และ Time to Interactive มักมีน้อย และสามารถแสดงผลหน้าเว็บได้ทันทีในขณะที่กำลังสตรีม HTML ไปยังเบราว์เซอร์

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

    • การแสดงผลแบบคงที่
      เราสร้างผลิตภัณฑ์เป็นแอปพลิเคชันหน้าเดียว แต่หน้าทั้งหมดแสดงผลล่วงหน้าเป็น HTML แบบคงที่โดยมี JavaScript น้อยที่สุดเป็นขั้นตอนการสร้าง นั่นหมายความว่าด้วยการแสดงผลแบบคงที่ เราสร้างไฟล์ HTML แต่ละไฟล์ สำหรับทุกๆ URL ที่เป็นไปได้ ล่วงหน้า ซึ่งเป็นสิ่งที่แอปพลิเคชันจำนวนมากไม่สามารถจ่ายได้ แต่เนื่องจากไม่จำเป็นต้องสร้าง HTML สำหรับหน้าเว็บในทันที เราจึงสามารถบรรลุ Time To First Byte ได้อย่างรวดเร็วอย่างสม่ำเสมอ ดังนั้น เราจึงสามารถแสดงหน้า Landing Page ได้อย่างรวดเร็ว จากนั้นจึงดึงข้อมูลกรอบงาน SPA ล่วงหน้าสำหรับหน้าถัดไป Netflix ได้ใช้แนวทางนี้เพื่อลดการโหลดและเวลาในการโต้ตอบลง 50%

    • การแสดงผลฝั่งเซิร์ฟเวอร์ด้วย (Re)Hydration (การแสดงผลแบบสากล, SSR + CSR)
      เราสามารถลองใช้สิ่งที่ดีที่สุดของทั้งสองโลก — แนวทาง SSR และ CSR ด้วยการไฮเดรชั่นในการผสม หน้า HTML ที่ส่งคืนจากเซิร์ฟเวอร์ยังมีสคริปต์ที่โหลดแอปพลิเคชันฝั่งไคลเอ็นต์ที่มีคุณสมบัติครบถ้วน เป็นการดีที่จะบรรลุ First Contentful Paint ที่รวดเร็ว (เช่น SSR) จากนั้นจึงทำการเรนเดอร์ต่อ (อีกครั้ง) ไฮเดรชั่น น่าเสียดายที่ไม่ค่อยเป็นเช่นนั้น บ่อยครั้ง หน้าดูเหมือนพร้อมแต่ไม่สามารถตอบสนองต่อการป้อนข้อมูลของผู้ใช้ ทำให้เกิดการคลิกอย่างเดือดดาลและการละทิ้ง

      ด้วย React เราสามารถใช้โมดูล ReactDOMServer บนเซิร์ฟเวอร์ Node เช่น Express จากนั้นเรียกใช้เมธอด renderToString เพื่อแสดงส่วนประกอบระดับบนสุดเป็นสตริง HTML แบบคงที่

      ด้วย Vue.js เราสามารถใช้ vue-server-renderer เพื่อแสดงอินสแตนซ์ Vue เป็น HTML โดยใช้ renderToString ใน Angular เราสามารถใช้ @nguniversal เพื่อเปลี่ยนคำขอของไคลเอ็นต์ให้เป็นหน้า HTML ที่แสดงผลโดยเซิร์ฟเวอร์ทั้งหมด ประสบการณ์การแสดงผลเซิร์ฟเวอร์อย่างสมบูรณ์สามารถทำได้ทันทีด้วย Next.js (React) หรือ Nuxt.js (Vue)

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

    • การสตรีมการแสดงผลฝั่งเซิร์ฟเวอร์ด้วย Progressive Hydration (SSR + CSR)
      เพื่อลดช่องว่างระหว่าง Time To Interactive และ First Contentful Paint เราแสดงคำขอหลายรายการพร้อมกัน และ ส่งเนื้อหาลง เป็นส่วนๆ เมื่อสร้างขึ้น ดังนั้น เราไม่ต้องรอให้ HTML เต็มสตริงก่อนที่จะส่งเนื้อหาไปยังเบราว์เซอร์ และปรับปรุง Time To First Byte

      ใน React แทนที่จะใช้ renderToString() เราสามารถใช้ renderToNodeStream() เพื่อไพพ์การตอบสนองและส่ง HTML ลงเป็นส่วนๆ ใน Vue เราสามารถใช้ renderToStream() ที่สามารถไพพ์และสตรีมได้ ด้วย React Suspense เราอาจใช้การเรนเดอร์แบบอะซิงโครนัสเพื่อจุดประสงค์นั้นเช่นกัน

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

      สำหรับ Vue Markus Oberlehner ได้เผยแพร่คู่มือเกี่ยวกับการลด Time To Interactive ของแอป SSR โดยใช้การดื่มน้ำในการโต้ตอบกับผู้ใช้ เช่นเดียวกับ vue-lazy-hydration ซึ่งเป็นปลั๊กอินระยะเริ่มต้นที่ช่วยให้ส่วนประกอบชุ่มชื้นในการมองเห็นหรือการโต้ตอบของผู้ใช้ที่เฉพาะเจาะจง ทีมงาน Angular พัฒนาการให้ความชุ่มชื้นแบบก้าวหน้าด้วย Ivy Universal คุณสามารถใช้การเติมน้ำบางส่วนด้วย Preact และ Next.js ได้เช่นกัน

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

    ภาพประกอบแสดงการทำงานของการเรนเดอร์ trisomorphic ใน 3 ที่ เช่น การเรนเดอร์ DOM การแสดงล่วงหน้าของเจ้าหน้าที่บริการ และการแสดงผลฝั่งเซิร์ฟเวอร์
    การเรนเดอร์ Trisomorphic ด้วยการแสดงโค้ดเดียวกันใน 3 แห่ง: บนเซิร์ฟเวอร์ ใน DOM หรือในพนักงานบริการ (ที่มาของรูปภาพ: Google Developers) (ตัวอย่างขนาดใหญ่)
    • CSR พร้อมการแสดงผลล่วงหน้า
      การแสดงผลล่วงหน้าคล้ายกับการแสดงผลฝั่งเซิร์ฟเวอร์ แต่แทนที่จะแสดงหน้าเว็บบนเซิร์ฟเวอร์แบบไดนามิก เราทำให้แอปพลิเคชันเป็น HTML แบบคงที่ ณ เวลาที่สร้าง แม้ว่าหน้าสแตติกจะโต้ตอบได้อย่างสมบูรณ์โดยไม่มี JavaScript ฝั่งไคลเอ็นต์มากนัก การ แสดงผลล่วงหน้าทำงานต่างกัน โดยพื้นฐานแล้วจะบันทึกสถานะเริ่มต้นของแอปพลิเคชันฝั่งไคลเอ็นต์เป็น HTML แบบคงที่ ณ เวลาสร้าง ในขณะที่การแสดงผลล่วงหน้า แอปพลิเคชันจะต้องบูตบนไคลเอ็นต์เพื่อให้หน้าเว็บโต้ตอบได้

      ด้วย Next.js เราสามารถใช้การส่งออก HTML แบบคงที่โดยการแสดงผลแอปล่วงหน้าเป็น HTML แบบคงที่ ใน Gatsby ตัวสร้างไซต์คงที่แบบโอเพนซอร์สที่ใช้ React ใช้วิธี renderToStaticMarkup แทนเมธอด renderToString ระหว่างการสร้าง โดยจะมีการโหลด JS หลักล่วงหน้าและเส้นทางในอนาคตจะถูกดึงข้อมูลล่วงหน้า โดยไม่มีแอตทริบิวต์ DOM ที่ไม่จำเป็นสำหรับเพจสแตติกอย่างง่าย

      สำหรับ Vue เราสามารถใช้ Vuepress เพื่อให้บรรลุเป้าหมายเดียวกันได้ คุณยังสามารถใช้ตัวโหลดล่วงหน้ากับ Webpack Navi ให้การเรนเดอร์แบบคงที่เช่นกัน

      ผลลัพธ์ที่ได้คือ Time To First Byte และ First Contentful Paint ที่ดีขึ้น และเราลดช่องว่างระหว่าง Time To Interactive และ First Contentful Paint เราไม่สามารถใช้วิธีนี้ได้หากคาดว่าเนื้อหาจะเปลี่ยนแปลงไปมาก นอกจากนี้ ต้องทราบ URL ทั้งหมดล่วงหน้าเพื่อสร้างหน้าทั้งหมด ดังนั้นองค์ประกอบบางอย่างอาจแสดงผลโดยใช้การแสดงผลล่วงหน้า แต่ถ้าเราต้องการสิ่งที่เป็นไดนามิก เราต้องพึ่งพาแอปเพื่อดึงเนื้อหา

    • การแสดงผลฝั่งไคลเอ็นต์แบบเต็ม (CSR)
      ตรรกะ การเรนเดอร์ และการบูตทั้งหมดเสร็จสิ้นบนไคลเอนต์ ผลลัพธ์ที่ได้มักจะเป็นช่องว่าง ขนาดใหญ่ ระหว่าง Time To Interactive และ First Contentful Paint ด้วยเหตุนี้ แอปพลิเคชันต่างๆ มักจะรู้สึกเฉื่อย เนื่องจากต้องบูตแอปทั้งหมดบนไคลเอ็นต์เพื่อแสดงผลอะไรก็ได้

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

      โดยทั่วไป SSR จะเร็วกว่า CSR ถึงกระนั้นก็ยังเป็นการใช้งานที่ค่อนข้างบ่อยสำหรับแอพจำนวนมากที่มีอยู่

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

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

ตารางเปรียบเทียบตัวเลือกสำหรับการแสดงผลฝั่งไคลเอ็นต์กับฝั่งเซิร์ฟเวอร์
สเปกตรัมของตัวเลือกสำหรับการแสดงผลฝั่งไคลเอ็นต์กับฝั่งเซิร์ฟเวอร์ นอกจากนี้ ตรวจสอบการพูดคุยของ Jason และ Houssein ที่ Google I/O เกี่ยวกับผลกระทบด้านประสิทธิภาพของสถาปัตยกรรมแอปพลิเคชัน (ที่มาของรูปภาพ: Jason Miller) (ตัวอย่างขนาดใหญ่)
ตัวอย่างเว็บไซต์ของ AirBnB ที่แสดงโดยไม่มีการเติมน้ำทางด้านซ้าย และมีการเติมความชุ่มชื้นทางด้านขวา
AirBnB ได้ทำการทดลองเกี่ยวกับการให้น้ำแบบก้าวหน้า พวกเขาเลื่อนส่วนประกอบที่ไม่จำเป็นออกไป โหลดในการโต้ตอบกับผู้ใช้ (เลื่อน) หรือในช่วงเวลาว่างและการทดสอบแสดงให้เห็นว่าสามารถปรับปรุง TTI ได้ (ตัวอย่างขนาดใหญ่)
  1. เราสามารถให้บริการแบบคงที่ได้มากแค่ไหน?
    ไม่ว่าคุณจะทำงานบนแอปพลิเคชันขนาดใหญ่หรือไซต์ขนาดเล็ก ควรพิจารณาว่าเนื้อหาใดบ้างที่สามารถให้ บริการแบบสแตติกจาก CDN (เช่น JAM Stack) แทนที่จะสร้างแบบไดนามิกได้ทันที แม้ว่าคุณจะมีผลิตภัณฑ์นับพันรายการและตัวกรองหลายร้อยรายการพร้อมตัวเลือกการปรับเปลี่ยนในแบบของคุณ คุณยังอาจต้องการให้บริการหน้า Landing Page ที่สำคัญของคุณแบบคงที่ และแยกหน้าเหล่านี้ออกจากกรอบงานที่คุณเลือก

    มีตัวสร้างไซต์คงที่มากมาย และหน้าที่สร้างมักจะเร็วมาก The more content we can pre-build ahead of time instead of generating page views on a server or client at request time, the better performance we will achieve.

    In Building Partially Hydrated, Progressively Enhanced Static Websites, Markus Oberlehner shows how to build out websites with a static site generator and an SPA, while achieving progressive enhancement and a minimal JavaScript bundle size. Markus uses Eleventy and Preact as his tools, and shows how to set up the tools, add partial hydration, lazy hydration, client entry file, configure Babel for Preact and bundle Preact with Rollup — from start to finish.

    With JAMStack used on large sites these days, a new performance consideration appeared: the build time . In fact, building out even thousands of pages with every new deploy can take minutes, so it's promising to see incremental builds in Gatsby which improve build times by 60 times , with an integration into popular CMS solutions like WordPress, Contentful, Drupal, Netlify CMS and others.

    A flow chart showing User 1 on the top left and User 2 on the bottom left showing the process of incremental status re-generation
    Incremental static regeneration with Next.js. (Image credit: Prisma.io) (Large preview)

    Also, Next.js announced ahead-of-time and incremental static generation, which allows us to add new static pages at runtime and update existing pages after they've been already built, by re-rendering them in the background as traffic comes in.

    Need an even more lightweight approach? In his talk on Eleventy, Alpine and Tailwind: towards a lightweight Jamstack, Nicola Goutay explains the differences between CSR, SSR and everything-in-between, and shows how to use a more lightweight approach — along with a GitHub repo that shows the approach in practice.

  2. Consider using PRPL pattern and app shell architecture.
    Different frameworks will have different effects on performance and will require different strategies of optimization, so you have to clearly understand all of the nuts and bolts of the framework you'll be relying on. When building a web app, look into the PRPL pattern and application shell architecture. The idea is quite straightforward: Push the minimal code needed to get interactive for the initial route to render quickly, then use service worker for caching and pre-caching resources and then lazy-load routes that you need, asynchronously.
PRPL Pattern in the application shell architecture
PRPL stands for Pushing critical resource, Rendering initial route, Pre-caching remaining routes and Lazy-loading remaining routes on demand.
Application shell architecture
An application shell is the minimal HTML, CSS, and JavaScript powering a user interface.
  1. Have you optimized the performance of your APIs?
    APIs are communication channels for an application to expose data to internal and third-party applications via endpoints . When designing and building an API, we need a reasonable protocol to enable the communication between the server and third-party requests. Representational State Transfer ( REST ) is a well-established, logical choice: it defines a set of constraints that developers follow to make content accessible in a performant, reliable and scalable fashion. Web services that conform to the REST constraints, are called RESTful web services .

    As with good ol' HTTP requests, when data is retrieved from an API, any delay in server response will propagate to the end user, hence delaying rendering . When a resource wants to retrieve some data from an API, it will need to request the data from the corresponding endpoint. A component that renders data from several resources, such as an article with comments and author photos in each comment, may need several roundtrips to the server to fetch all the data before it can be rendered. Furthermore, the amount of data returned through REST is often more than what is needed to render that component.

    If many resources require data from an API, the API might become a performance bottleneck. GraphQL provides a performant solution to these issues. Per se, GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. Unlike REST, GraphQL can retrieve all data in a single request , and the response will be exactly what is required, without over or under -fetching data as it typically happens with REST.

    In addition, because GraphQL is using schema (metadata that tells how the data is structured), it can already organize data into the preferred structure, so, for example, with GraphQL, we could remove JavaScript code used for dealing with state management, producing a cleaner application code that runs faster on the client.

    If you want to get started with GraphQL or encounter performance issues, these articles might be quite helpful:

    • A GraphQL Primer: Why We Need A New Kind Of API by Eric Baer,
    • A GraphQL Primer: The Evolution Of API Design by Eric Baer,
    • Designing a GraphQL server for optimal performance by Leonardo Losoviz,
    • GraphQL performance explained by Wojciech Trocki.
Two examples of mobile interfaces for messages while using Redux/REST (left) and Apollo/GraphQL (right)
A difference between REST and GraphQL, illustrated via a conversation between Redux + REST on the left, an Apollo + GraphQL on the right. (Image source: Hacker Noon) (Large preview)
  1. Will you be using AMP or Instant Articles?
    Depending on the priorities and strategy of your organization, you might want to consider using Google's AMP or Facebook's Instant Articles or Apple's Apple News. You can achieve good performance without them, but AMP does provide a solid performance framework with a free content delivery network (CDN), while Instant Articles will boost your visibility and performance on Facebook.

    The seemingly obvious benefit of these technologies for users is guaranteed performance , so at times they might even prefer AMP-/Apple News/Instant Pages-links over "regular" and potentially bloated pages. For content-heavy websites that are dealing with a lot of third-party content, these options could potentially help speed up render times dramatically.

    Unless they don't. According to Tim Kadlec, for example, "AMP documents tend to be faster than their counterparts, but they don't necessarily mean a page is performant. AMP is not what makes the biggest difference from a performance perspective."

    A benefit for the website owner is obvious: discoverability of these formats on their respective platforms and increased visibility in search engines.

    Well, at least that's how it used to be. As AMP is no longer a requirement for Top Stories , publishers might be moving away from AMP to a traditional stack instead ( thanks, Barry! ).

    Still, you could build progressive web AMPs, too, by reusing AMPs as a data source for your PWA. Downside? Obviously, a presence in a walled garden places developers in a position to produce and maintain a separate version of their content, and in case of Instant Articles and Apple News without actual URLs (thanks Addy, Jeremy!) .

  2. Choose your CDN wisely.
    As mentioned above, depending on how much dynamic data you have, you might be able to "outsource" some part of the content to a static site generator, pushing it to a CDN and serving a static version from it, thus avoiding requests to the server. In fact, some of those generators are actually website compilers with many automated optimizations provided out of the box. As compilers add optimizations over time, the compiled output gets smaller and faster over time.

    Notice that CDNs can serve (and offload) dynamic content as well. So, restricting your CDN to static assets is not necessary. Double-check whether your CDN performs compression and conversion (eg image optimization and resizing at the edge), whether they provide support for servers workers, A/B testing, as well as edge-side includes, which assemble static and dynamic parts of pages at the CDN's edge (ie the server closest to the user), and other tasks. Also, check if your CDN supports HTTP over QUIC (HTTP/3).

    Katie Hempenius has written a fantastic guide to CDNs that provides insights on how to choose a good CDN , how to finetune it and all the little things to keep in mind when evaluating one. In general, it's a good idea to cache content as aggressively as possible and enable CDN performance features like Brotli, TLS 1.3, HTTP/2, and HTTP/3.

    Note : based on research by Patrick Meenan and Andy Davies, HTTP/2 prioritization is effectively broken on many CDNs, so be careful when choosing a CDN. Patrick has more details in his talk on HTTP/2 Prioritization ( thanks, Barry! ).

    CDNPerf preview of CDN names and query speed in ms
    CDNPerf measures query speed for CDNs by gathering and analyzing 300 million tests every day. (ตัวอย่างขนาดใหญ่)

    When choosing a CDN, you can use these comparison sites with a detailed overview of their features:

    • CDN Comparison, เมทริกซ์เปรียบเทียบ CDN สำหรับ Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai และอื่นๆ อีกมากมาย
    • CDN Perf วัดความเร็วการสืบค้นสำหรับ CDN โดยรวบรวมและวิเคราะห์การทดสอบ 300 ล้านครั้งทุกวัน โดยผลลัพธ์ทั้งหมดอิงตามข้อมูล RUM จากผู้ใช้ทั่วโลก ตรวจสอบการเปรียบเทียบประสิทธิภาพ DNS และการเปรียบเทียบประสิทธิภาพของคลาวด์ด้วย
    • CDN Planet Guides ให้ภาพรวมของ CDN สำหรับหัวข้อเฉพาะ เช่น Serve Stale, Purge, Origin Shield, Prefetch และ Compression
    • เว็บปูม: การนำ CDN และการใช้งานมาใช้ให้ข้อมูลเชิงลึกเกี่ยวกับผู้ให้บริการ CDN ชั้นนำ การจัดการ RTT และ TLS เวลาในการเจรจา TLS การปรับใช้ HTTP/2 และอื่นๆ (น่าเสียดายที่ข้อมูลเป็นข้อมูลตั้งแต่ปี 2019 เท่านั้น)

การเพิ่มประสิทธิภาพสินทรัพย์

  1. ใช้ Brotli สำหรับการบีบอัดข้อความธรรมดา
    ในปี 2015 Google ได้เปิดตัว Brotli ซึ่งเป็นรูปแบบข้อมูลแบบไม่สูญเสียโอเพนซอร์สรูปแบบใหม่ ซึ่งขณะนี้ได้รับการสนับสนุนในเบราว์เซอร์รุ่นใหม่ทั้งหมด ไลบรารี Brotli แบบโอเพนซอร์สที่ใช้ตัวเข้ารหัสและตัวถอดรหัสสำหรับ Brotli มีระดับคุณภาพที่กำหนดไว้ล่วงหน้า 11 ระดับสำหรับตัวเข้ารหัส โดยระดับคุณภาพที่สูงกว่าต้องการ CPU มากขึ้นเพื่อแลกกับอัตราส่วนการบีบอัดที่ดีขึ้น การบีบอัดที่ช้าลงในที่สุดจะนำไปสู่อัตราการบีบอัดที่สูงขึ้น แต่ถึงกระนั้น Brotli จะคลายการบีบอัดอย่างรวดเร็ว เป็นที่น่าสังเกตว่า Brotli ที่มีระดับการบีบอัด 4 นั้นเล็กกว่าและบีบอัดได้เร็วกว่า Gzip

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

    เบราว์เซอร์จะยอมรับ Brotli เฉพาะเมื่อผู้ใช้เข้าชมเว็บไซต์ผ่าน HTTPS รองรับ Brotli อย่างกว้างขวางและ CDN จำนวนมากรองรับ (Akamai, Netlify Edge, AWS, KeyCDN, Fastly (ปัจจุบันเป็นแบบพาส-ทรูเท่านั้น), Cloudflare, CDN77) และคุณสามารถเปิดใช้งาน Brotli ได้แม้ใน CDN ที่ยังไม่รองรับ (มีพนักงานบริการ).

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

    การเปรียบเทียบที่แสดงเป็นแผนภูมิมัสสุซึ่งแสดงวิธีการบีบอัดต่างๆ ในช่วงเวลาแบ็คเอนด์ที่แตกต่างกัน 3 ครั้ง ได้แก่ ค่าเปอร์เซ็นไทล์ต่ำสุด ค่าเฉลี่ย และเปอร์เซ็นไทล์ที่ 90
    การเปรียบเทียบเวลาแบ็กเอนด์ของวิธีการบีบอัดต่างๆ ไม่น่าแปลกใจเลยที่ Brotli ช้ากว่า gzip (สำหรับตอนนี้) (ตัวอย่างขนาดใหญ่)

    นี้อาจมีการเปลี่ยนแปลงแม้ว่า รูปแบบไฟล์ Brotli ประกอบด้วย พจนานุกรมสแตติกใน ตัว และนอกจากจะประกอบด้วยสตริงต่างๆ ในหลายภาษาแล้ว ยังสนับสนุนตัวเลือกในการใช้การแปลงหลายคำกับคำเหล่านั้น เพิ่มความเก่งกาจของคำเหล่านั้น ในการวิจัยของเขา เฟลิกซ์ ฮาเนาได้ค้นพบวิธีปรับปรุงการบีบอัดที่ระดับ 5 ถึง 9 โดยใช้ "ชุดย่อยของพจนานุกรมที่เชี่ยวชาญกว่าค่าเริ่มต้น" และอาศัยส่วนหัว Content-Type เพื่อบอกคอมเพรสเซอร์ว่าควรใช้ พจนานุกรมสำหรับ HTML, JavaScript หรือ CSS ผลที่ได้คือ "ผลกระทบต่อประสิทธิภาพเล็กน้อย (ซีพียูเพิ่มขึ้น 1% ถึง 3% เมื่อเทียบกับปกติ 12%) เมื่อบีบอัดเนื้อหาเว็บที่ระดับการบีบอัดสูงโดยใช้แนวทางการใช้พจนานุกรมที่จำกัด"

    แผนภูมิแท่งแสดงอัตราขยายของการบีบอัดโดยใช้พจนานุกรมที่ลดขนาดพจนานุกรมของ Brotli ที่ระดับ 5
    ด้วยวิธีพจนานุกรมที่ได้รับการปรับปรุง เราสามารถบีบอัดเนื้อหาได้เร็วขึ้นในระดับการบีบอัดที่สูงขึ้น โดยใช้ CPU เพิ่มขึ้นเพียง 1% ถึง 3% โดยปกติ การบีบอัดระดับ 6 มากกว่า 5 จะเพิ่มการใช้งาน CPU ได้ถึง 12% (ตัวอย่างขนาดใหญ่)

    ยิ่งไปกว่านั้น ด้วยการวิจัยของ Elena Kirilenko เราสามารถ บีบอัด Brotli ได้อย่างรวดเร็วและมีประสิทธิภาพ โดยใช้สิ่งประดิษฐ์ในการบีบอัดก่อนหน้า ตามที่ Elena กล่าวว่า "เมื่อเรามีเนื้อหาที่ถูกบีบอัดผ่าน Brotli และเรากำลังพยายามบีบอัดเนื้อหาแบบไดนามิกในทันที โดยที่เนื้อหานั้นคล้ายกับเนื้อหาที่เรามีอยู่ก่อนเวลา เราสามารถปรับปรุงเวลาในการบีบอัดได้อย่างมีนัยสำคัญ "

    บ่อยแค่ไหน? เช่น การส่ง ชุดย่อยของบันเดิล JavaScript (เช่น เมื่อส่วนของโค้ดถูกแคชบนไคลเอ็นต์แล้ว หรือกับบันเดิลแบบไดนามิกที่ให้บริการกับ WebBundles) หรือด้วย HTML แบบไดนามิกตามเทมเพลตที่รู้จักล่วงหน้า หรือ ฟอนต์ WOFF2 ที่ตั้งค่าย่อยแบบไดนามิก จากข้อมูลของ Elena เราสามารถปรับปรุงการบีบอัดได้ 5.3% และความเร็วการบีบอัดดีขึ้น 39% เมื่อลบเนื้อหาออก 10% และอัตราการบีบอัดดีขึ้น 3.2% และการบีบอัดเร็วขึ้น 26% เมื่อลบเนื้อหาออก 50%

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

    หมายเหตุ : เมื่อต้นปี 2021 การตอบสนอง HTTP ประมาณ 60% ถูกส่งโดยไม่มีการบีบอัดแบบข้อความ โดยมีการบีบอัด 30.82% ด้วย Gzip และ 9.1% ที่บีบอัดด้วย Brotli (ทั้งบนมือถือและบนเดสก์ท็อป) เช่น 23.4% ของเพจเชิงมุมไม่ถูกบีบอัด (ผ่าน gzip หรือ Brotli) การเปิดการบีบอัดข้อมูลบ่อยครั้งเป็นหนึ่งในวิธีที่ง่ายที่สุดในการปรับปรุงประสิทธิภาพด้วยการพลิกสวิตช์ง่ายๆ

    กลยุทธ์? บีบอัดไฟล์สแตติกล่วงหน้าด้วย Brotli+Gzip ที่ระดับสูงสุด และบีบอัด HTML (ไดนามิก) ได้ทันทีด้วย Brotli ที่ระดับ 4-6 ตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์จัดการการเจรจาเนื้อหาสำหรับ Brotli หรือ Gzip อย่างถูกต้อง

แผนภูมิแท่งแสดงอัลกอริธึมการบีบอัดสำหรับคำขอ HTTP ตามรายงาน Web Almanax 2020
จากทรัพยากรที่บีบอัดในปี 2020 นั้น 22.59% ถูกบีบอัดด้วย Brotli ประมาณ 77.39% ถูกบีบอัดด้วย gzip (ที่มาของรูปภาพ: Web Almanac: การบีบอัด) (ตัวอย่างขนาดใหญ่)
  1. เราใช้การโหลดสื่อที่ปรับเปลี่ยนได้และคำแนะนำลูกค้าหรือไม่
    มันมาจากดินแดนแห่งข่าวเก่า แต่ก็เป็นการเตือนที่ดีเสมอที่จะใช้ภาพที่ตอบสนองด้วย srcset sizes และองค์ประกอบ <picture> โดยเฉพาะอย่างยิ่งสำหรับไซต์ที่มีสื่อจำนวนมาก เราสามารถก้าวไปอีกขั้นด้วยการโหลดสื่อที่ปรับเปลี่ยนได้ (ในตัวอย่างนี้ React + Next.js) ซึ่งให้บริการ ประสบการณ์แสงแก่เครือข่ายที่ช้า และอุปกรณ์หน่วยความจำต่ำ และประสบการณ์เต็มรูปแบบไปยังเครือข่ายที่รวดเร็วและสูง - อุปกรณ์หน่วยความจำ ในบริบทของ React เราสามารถทำได้ด้วยคำแนะนำไคลเอนต์บนเซิร์ฟเวอร์และ react-adaptive-hooks บนไคลเอนต์

    อนาคตของภาพที่ตอบสนองอาจเปลี่ยนไปอย่างมากด้วยการนำคำแนะนำลูกค้ามาใช้ในวงกว้าง คำแนะนำไคลเอ็นต์คือฟิลด์ส่วนหัวคำขอ HTTP เช่น DPR , Viewport-Width , Width , Save-Data , Accept (เพื่อระบุการตั้งค่ารูปแบบรูปภาพ) และอื่นๆ พวกเขาควรจะแจ้งเซิร์ฟเวอร์เกี่ยวกับลักษณะเฉพาะของเบราว์เซอร์ หน้าจอ การเชื่อมต่อ ฯลฯ ของผู้ใช้

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

    ภาพประกอบแสดงให้เห็นว่าการให้บริการสื่อที่ปรับเปลี่ยนได้นั้นสามารถใช้โดยส่งความละเอียดที่แตกต่างกันไปยังผู้ใช้ตามความสามารถของเครือข่าย
    สื่อดัดแปลงที่ให้บริการในการใช้งาน เราส่งตัวยึดตำแหน่งพร้อมข้อความไปยังผู้ใช้ที่ออฟไลน์ รูปภาพความละเอียดต่ำไปยังผู้ใช้ 2G รูปภาพความละเอียดสูงไปยังผู้ใช้ 3G และวิดีโอ HD ไปยังผู้ใช้ 4G ผ่านการโหลดหน้าเว็บอย่างรวดเร็วบนฟีเจอร์โฟนราคา $20 (ตัวอย่างขนาดใหญ่)

    ดังที่ Ilya Grigorik ได้กล่าวไว้ก่อนหน้านี้ คำใบ้ของลูกค้าทำให้รูปภาพสมบูรณ์ — สิ่งเหล่านี้ไม่ใช่ทางเลือกอื่นสำหรับรูปภาพที่ตอบสนอง "องค์ประกอบ <picture> ให้การควบคุมทิศทางศิลปะที่จำเป็นในมาร์กอัป HTML คำแนะนำของไคลเอ็นต์ให้คำอธิบายประกอบเกี่ยวกับคำขอรูปภาพที่เป็นผลลัพธ์ซึ่งเปิดใช้งานการเลือกทรัพยากรอัตโนมัติ เจ้าหน้าที่บริการให้คำขอเต็มรูปแบบและความสามารถในการจัดการการตอบสนองบนไคลเอ็นต์"

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

    สำหรับลูกค้าที่สนับสนุนคำแนะนำลูกค้า เราสามารถวัดการประหยัดไบต์ 42% สำหรับรูปภาพ และ 1MB+ ไบต์น้อยกว่าสำหรับเปอร์เซ็นไทล์ที่ 70+ ใน Smashing Magazine เราสามารถวัดการปรับปรุง 19-32% ได้เช่นกัน คำแนะนำไคลเอ็นต์ได้รับการสนับสนุนในเบราว์เซอร์ที่ใช้ Chromium แต่ยังอยู่ระหว่างการพิจารณาใน Firefox

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

  2. เราใช้ภาพที่ตอบสนองสำหรับภาพพื้นหลังหรือไม่?
    เราควรจะ! ด้วย image-set ขณะนี้รองรับใน Safari 14 และในเบราว์เซอร์ที่ทันสมัยส่วนใหญ่ ยกเว้น Firefox เราสามารถแสดงภาพพื้นหลังที่ตอบสนองได้เช่นกัน:

    background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);

    โดยพื้นฐานแล้ว เราสามารถแสดงภาพพื้นหลังความละเอียดต่ำแบบมีเงื่อนไขด้วยตัวบอก 1x และรูปภาพที่มีความละเอียดสูงกว่าด้วยตัวอธิบาย 2x และแม้แต่ภาพคุณภาพการพิมพ์ที่มีตัวบอก 600dpi ระวัง: เบราว์เซอร์ไม่ได้ให้ข้อมูลพิเศษใดๆ เกี่ยวกับภาพพื้นหลังแก่เทคโนโลยีอำนวยความสะดวก ดังนั้นตามหลักแล้วภาพถ่ายเหล่านี้ควรเป็นเพียงการตกแต่งเท่านั้น

  3. เราใช้ WebP หรือไม่
    การบีบอัดรูปภาพมักจะถือว่าได้ผลอย่างรวดเร็ว แต่ก็ยังใช้งานไม่ได้จริงในทางปฏิบัติ แน่นอนว่ารูปภาพไม่ได้บล็อกการเรนเดอร์ แต่มันมีส่วนอย่างมากต่อคะแนน LCP ที่ไม่ดี และบ่อยครั้งก็หนักและใหญ่เกินไปสำหรับอุปกรณ์ที่ใช้

    อย่างน้อยที่สุด เราสามารถสำรวจโดยใช้รูปแบบ WebP สำหรับรูปภาพของเรา ในความเป็นจริง WebP saga นั้นใกล้จะถึงจุดสิ้นสุดแล้วในปีที่แล้ว โดย Apple ได้เพิ่มการรองรับ WebP ใน Safari 14 ดังนั้นหลังจากหลายปีของการอภิปรายและการอภิปราย ณ วันนี้ WebP ได้รับการสนับสนุนในเบราว์เซอร์ที่ทันสมัยทั้งหมด ดังนั้นเราจึงสามารถให้บริการรูปภาพ WebP ด้วยองค์ประกอบ <picture> และ JPEG fallback หากจำเป็น (ดูข้อมูลโค้ดของ Andreas Bovens) หรือโดยใช้การต่อรองเนื้อหา (โดยใช้ส่วนหัวที่ Accept )

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

    การตัดสินใจของคุณจะขึ้นอยู่กับสิ่งที่คุณกำลังติดตาม: ด้วย WebP คุณจะลดเพย์โหลด และด้วย JPEG คุณจะปรับปรุงประสิทธิภาพการรับรู้ คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ WebP ได้ใน WebP Rewind talk โดย Pascal Massimino ของ Google

    สำหรับการแปลงเป็น WebP คุณสามารถใช้ WebP Converter, cwebp หรือ libwebp Ire Aderinokun มีบทช่วยสอนที่มีรายละเอียดมากเกี่ยวกับการแปลงรูปภาพเป็น WebP เช่นกัน — และ Josh Comeau ก็มีส่วนร่วมในรูปแบบภาพสมัยใหม่ด้วยเช่นกัน

    สไลด์ที่ใช้สำหรับการบรรยายของ Pascal Massimino ในหัวข้อ Image ready: webp rewind
    การพูดคุยอย่างละเอียดเกี่ยวกับ WebP: WebP Rewind โดย Pascal Massimino (ตัวอย่างขนาดใหญ่)

    Sketch รองรับ WebP และสามารถส่งออกรูปภาพ WebP จาก Photoshop โดยใช้ปลั๊กอิน WebP สำหรับ Photoshop แต่มีตัวเลือกอื่นด้วย

    หากคุณใช้ WordPress หรือ Joomla มีส่วนขยายต่างๆ ที่จะช่วยให้คุณปรับใช้การสนับสนุน WebP ได้อย่างง่ายดาย เช่น Optimus และ Cache Enabler สำหรับ WordPress และส่วนขยายที่รองรับของ Joomla (ผ่าน Cody Arsenault) คุณยังสามารถแยกองค์ประกอบ <picture> ด้วย React ส่วนประกอบที่มีสไตล์ หรือ gatsby-image

    อ่า - ปลั๊กไร้ยางอาย! — Jeremy Wagner ได้ตีพิมพ์หนังสือ Smashing บน WebP ซึ่งคุณอาจต้องการตรวจสอบว่าคุณสนใจทุกอย่างเกี่ยวกับ WebP หรือไม่

  4. เราใช้ AVIF หรือไม่?
    คุณอาจเคยได้ยินข่าวใหญ่: AVIF มาถึงแล้ว เป็นรูปแบบภาพใหม่ที่ได้จากคีย์เฟรมของวิดีโอ AV1 เป็นรูปแบบเปิดที่ไม่มีค่าลิขสิทธิ์ซึ่งรองรับการบีบอัดข้อมูลแบบ lossy และ lossless แอนิเมชัน ช่องอัลฟาแบบสูญเสียข้อมูล และสามารถจัดการกับเส้นที่คมชัดและสีทึบ (ซึ่งเป็นปัญหาของ JPEG) ในขณะที่ให้ผลลัพธ์ที่ดีกว่าทั้งคู่

    ที่จริงแล้ว เมื่อเปรียบเทียบกับ WebP และ JPEG แล้ว AVIF ทำงานได้ดีกว่าอย่างเห็นได้ชัด ทำให้สามารถประหยัดขนาดไฟล์มัธยฐานได้มากถึง 50% ที่ DSSIM ((dis)similarity เดียวกันระหว่างสองภาพขึ้นไปโดยใช้อัลกอริทึมที่ใกล้เคียงกับการมองเห็นของมนุษย์) ที่จริงแล้ว ในการโพสต์อย่างละเอียดของเขาเกี่ยวกับการเพิ่มประสิทธิภาพการโหลดรูปภาพ Malte Ubl ตั้งข้อสังเกตว่า AVIF "มีประสิทธิภาพเหนือกว่า JPEG อย่างมากในวิธีที่สำคัญมากอย่างสม่ำเสมอ ซึ่งแตกต่างจาก WebP ที่ไม่ได้ผลิตภาพที่เล็กกว่า JPEG เสมอไป และจริงๆ แล้วอาจเป็น net- สูญเสียเนื่องจากขาดการสนับสนุนสำหรับการโหลดแบบก้าวหน้า"

    ข้อมูลโค้ดที่แสดง AVIF เป็นการเพิ่มประสิทธิภาพแบบก้าวหน้า
    เราสามารถใช้ AVIF เป็นการเพิ่มประสิทธิภาพแบบก้าวหน้า โดยส่ง WebP หรือ JPEG หรือ PNG ไปยังเบราว์เซอร์รุ่นเก่า (ตัวอย่างขนาดใหญ่). ดูมุมมองข้อความธรรมดาด้านล่าง

    น่าแปลกที่ AVIF สามารถทำงานได้ดีกว่า SVG ขนาดใหญ่ แม้ว่าแน่นอนว่าไม่ควรถูกมองว่ามาแทนที่ SVG นอกจากนี้ยังเป็นหนึ่งในรูปแบบภาพแรกที่สนับสนุนการรองรับสี HDR; ให้ความสว่างที่สูงขึ้น ความลึกของบิตสี และขอบเขตสี ข้อเสียเพียงอย่างเดียวคือขณะนี้ AVIF ไม่รองรับการถอดรหัสภาพแบบโปรเกรสซีฟ (ยัง?) และเช่นเดียวกับ Brotli การเข้ารหัสที่มีอัตราการบีบอัดสูงในขณะนี้ค่อนข้างช้า แม้ว่าการถอดรหัสจะเร็ว

    ปัจจุบัน AVIF รองรับใน Chrome, Firefox และ Opera และการสนับสนุนใน Safari คาดว่าจะมาในเร็วๆ นี้ (เนื่องจาก Apple เป็นสมาชิกของกลุ่มที่สร้าง AV1)

    วิธีใด ดีที่สุดในการแสดงรูปภาพในทุกวันนี้ สำหรับภาพประกอบและภาพเวกเตอร์ (บีบอัด) SVG เป็นตัวเลือกที่ดีที่สุดอย่างไม่ต้องสงสัย สำหรับภาพถ่าย เราใช้วิธีการต่อรองเนื้อหากับองค์ประกอบ picture หากรองรับ AVIF เราจะส่งภาพ AVIF หากไม่เป็นเช่นนั้น เราจะถอยกลับไปที่ WebP ก่อน และหากไม่รองรับ WebP เราจะเปลี่ยนเป็น JPEG หรือ PNG เป็นทางเลือก (ใช้เงื่อนไข @media หากจำเป็น):

    <picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>

    ตรงไปตรงมา มีแนวโน้มมากกว่าที่เราจะใช้เงื่อนไขบางอย่างภายในองค์ประกอบ picture แม้ว่า:

    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>

    ไปได้ไกลยิ่งขึ้นด้วยการสลับภาพเคลื่อนไหวเป็นภาพนิ่งสำหรับลูกค้าที่เลือกให้เคลื่อนไหวน้อยลงโดย prefers-reduced-motion :

    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>

    ในช่วงสองสามเดือน AVIF ได้รับแรงฉุดค่อนข้างมาก:

    • เราสามารถทดสอบ WebP/AVIF fallbacks ในแผงการแสดงผลใน DevTools
    • เราสามารถใช้ Squoosh, AVIF.io และ libavif เพื่อเข้ารหัส ถอดรหัส บีบอัด และแปลงไฟล์ AVIF
    • เราสามารถใช้องค์ประกอบ AVIF Preact ของ Jake Archibald ที่ถอดรหัสไฟล์ AVIF ในตัวงานและแสดงผลบนผืนผ้าใบ
    • ในการส่ง AVIF ให้กับเบราว์เซอร์ที่รองรับเท่านั้น เราสามารถใช้ปลั๊กอิน PostCSS ร่วมกับสคริปต์ 315B เพื่อใช้ AVIF ในการประกาศ CSS ของคุณ
    • เราสามารถนำเสนอรูปแบบภาพใหม่ๆ ด้วย CSS และ Cloudlare Workers เพื่อแก้ไขเอกสาร HTML ที่ส่งคืนแบบไดนามิก โดยอนุมานข้อมูลจากส่วนหัวที่ accept และเพิ่มคลาส webp/avif เป็นต้น ตามความเหมาะสม
    • AVIF พร้อมใช้งานแล้วใน Cloudinary (โดยมีขีดจำกัดการใช้งาน) Cloudflare รองรับ AVIF ในการปรับขนาดรูปภาพ และคุณสามารถเปิดใช้งาน AVIF ด้วย Custom AVIF Headers ใน Netlify
    • เมื่อพูดถึงแอนิเมชั่น AVIF ทำงานได้ดีเช่นเดียวกับ <img src=mp4> ของ Safari ซึ่งดีกว่า GIF และ WebP โดยรวม แต่ MP4 ยังคงทำงานได้ดีกว่า
    • โดยทั่วไป สำหรับแอนิเมชั่น AVC1 (h264) > HVC1 > WebP > AVIF > GIF สมมติว่าเบราว์เซอร์ที่ใช้ Chromium จะรองรับ <img src=mp4>
    • คุณสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับ AVIF ได้ใน AVIF สำหรับ Next Generation Image Coding talk โดย Aditya Mavlankar จาก Netflix และ The AVIF Image Format โดย Kornel Lesinski ของ Cloudflare
    • ข้อมูลอ้างอิงที่ยอดเยี่ยมสำหรับทุกสิ่ง AVIF: โพสต์ที่ครอบคลุมของ Jake Archibald ใน AVIF มาถึงแล้ว

    AVIF ในอนาคต คือ? Jon Sneyers ไม่เห็นด้วย: AVIF ทำงานได้แย่กว่า JPEG XL ถึง 60% ซึ่งเป็นรูปแบบเปิดเสรีอีกรูปแบบหนึ่งที่พัฒนาโดย Google และ Cloudinary อันที่จริง ดูเหมือนว่า JPEG XL จะทำงานได้ดีกว่าทั่วๆ ไป อย่างไรก็ตาม JPEG XL ยังอยู่ในขั้นตอนสุดท้ายของการกำหนดมาตรฐานเท่านั้น และยังไม่สามารถใช้งานได้ในเบราว์เซอร์ใดๆ (เพื่อไม่ให้ปะปนกับ JPEG-XR ของ Microsoft ที่มาจาก Internet Explorer 9 รุ่นเก่าๆ)

ตัวสร้างเบรกพอยต์ที่ตอบสนอง
ตัวสร้างเบรกพอยต์ที่ตอบสนองของรูปภาพจะสร้างรูปภาพและมาร์กอัปโดยอัตโนมัติ
  1. JPEG/PNG/SVG ได้รับการปรับให้เหมาะสมอย่างเหมาะสมหรือไม่
    เมื่อคุณกำลังทำงานบนแลนดิ้งเพจซึ่งเป็นสิ่งสำคัญที่อิมเมจฮีโร่โหลดได้เร็วมาก ตรวจสอบให้แน่ใจว่า JPEG เป็นแบบโปรเกรสซีฟและบีบอัดด้วย mozJPEG (ซึ่งช่วยปรับปรุงเวลาในการแสดงผลเริ่มต้นโดยปรับระดับการสแกน) หรือ Guetzli ซึ่งเป็นโอเพ่นซอร์สของ Google ตัวเข้ารหัสมุ่งเน้นไปที่ประสิทธิภาพการรับรู้และใช้ประโยชน์จากการเรียนรู้จาก Zopfli และ WebP ข้อเสียเพียงอย่างเดียว: เวลาประมวลผลช้า (หนึ่งนาทีของ CPU ต่อเมกะพิกเซล)

    สำหรับ PNG เราสามารถใช้ Pingo และสำหรับ SVG เราสามารถใช้ SVGO หรือ SVGOMG และหากคุณต้องการดูตัวอย่างและคัดลอกหรือดาวน์โหลดเนื้อหา SVG ทั้งหมดจากเว็บไซต์อย่างรวดเร็ว svg-grabber ก็ช่วยคุณได้เช่นกัน

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

    นอกจากนี้ยังมีเครื่องมือออนไลน์ที่มีประโยชน์แม้ว่า:

    • ใช้ Squoosh เพื่อบีบอัด ปรับขนาด และจัดการรูปภาพในระดับการบีบอัดที่เหมาะสมที่สุด (สูญเสียหรือสูญเสีย)
    • ใช้ Guetzli.it เพื่อบีบอัดและปรับแต่งภาพ JPEG ให้เหมาะสมด้วย Guetzli ซึ่งทำงานได้ดีสำหรับภาพที่มีขอบคมและสีทึบ (แต่อาจช้ากว่าเล็กน้อย))
    • ใช้ Responsive Image Breakpoints Generator หรือบริการ เช่น Cloudinary หรือ Imgix เพื่อปรับภาพให้เหมาะสมโดยอัตโนมัติ นอกจากนี้ ในหลายกรณี การใช้ srcset และ sizes เพียงอย่างเดียวจะได้รับประโยชน์อย่างมาก
    • ในการตรวจสอบประสิทธิภาพของมาร์กอัปที่ตอบสนองของคุณ คุณสามารถใช้ Imaging-heap ซึ่งเป็นเครื่องมือบรรทัดคำสั่งที่วัดประสิทธิภาพตามขนาดวิวพอร์ตและอัตราส่วนพิกเซลของอุปกรณ์
    • คุณสามารถเพิ่มการบีบอัดรูปภาพอัตโนมัติให้กับเวิร์กโฟลว์ GitHub ของคุณได้ ดังนั้นจึงไม่มีรูปภาพใดที่จะบีบอัดการผลิตได้ การดำเนินการนี้ใช้ mozjpeg และ libvips ที่ทำงานกับ PNG และ JPG
    • ในการเพิ่มประสิทธิภาพการจัดเก็บข้อมูลภายใน คุณสามารถใช้รูปแบบ Lepton ใหม่ของ Dropbox เพื่อบีบอัด JPEG โดยไม่สูญเสียข้อมูลโดยเฉลี่ย 22%
    • ใช้ BlurHash หากคุณต้องการแสดงภาพที่พักก่อน BlurHash ใช้รูปภาพและให้สตริงสั้น ๆ (เพียง 20-30 อักขระเท่านั้น!) ที่แสดงถึงตัวยึดตำแหน่งสำหรับรูปภาพนี้ สตริงสั้นพอที่จะเพิ่มเป็นฟิลด์ในออบเจกต์ JSON ได้อย่างง่ายดาย
    การเปรียบเทียบอินเทอร์เฟซที่ไม่มีตัวยึดตำแหน่งรูปภาพทางด้านซ้ายและตัวยึดตำแหน่งที่แสดงทางด้านขวา
    BlurHash เป็นเพียงตัวแทนขนาดเล็กสำหรับรูปภาพ (ตัวอย่างขนาดใหญ่)

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

    • พิจารณาโหลดรูปภาพที่สำคัญไว้ล่วงหน้า เพื่อไม่ให้เบราว์เซอร์ค้นพบช้าเกินไป สำหรับภาพพื้นหลัง หากคุณต้องการก้าวร้าวมากกว่านั้น คุณสามารถเพิ่มภาพเป็นภาพปกติด้วย <img src> แล้วซ่อนไว้นอกหน้าจอ
    • พิจารณาการสลับรูปภาพด้วยแอตทริบิวต์ Sizes โดยการระบุขนาดการแสดงรูปภาพที่แตกต่างกันขึ้นอยู่กับการสืบค้นสื่อ เช่น การจัดการ sizes เพื่อสลับแหล่งที่มาในส่วนประกอบแว่นขยาย
    • ตรวจสอบความไม่สอดคล้องกันของการดาวน์โหลดรูปภาพเพื่อป้องกันการดาวน์โหลดที่ไม่คาดคิดสำหรับรูปภาพเบื้องหน้าและพื้นหลัง ระวังรูปภาพที่โหลดโดยค่าเริ่มต้น แต่อาจไม่ปรากฏ — เช่น ในภาพหมุน หีบเพลง และแกลเลอรี่ภาพ
    • ตรวจสอบให้แน่ใจว่าได้กำหนด width และ height ของรูปภาพเสมอ ระวังคุณสมบัติ aspect-ratio ในแอตทริบิวต์ intrinsicsize และแอตทริบิวต์ขนาดจริง ซึ่งจะทำให้เรากำหนดอัตราส่วนกว้างยาวและขนาดสำหรับรูปภาพได้ ดังนั้นเบราว์เซอร์จึงสามารถจองช่องเค้าโครงที่กำหนดไว้ล่วงหน้าไว้ล่วงหน้าเพื่อหลีกเลี่ยงการข้ามเค้าโครงระหว่างการโหลดหน้า
    สกรีนช็อตของโค้ดที่แสดงองค์ประกอบ padding-top และสัดส่วนภาพที่ใช้ในตัวแก้ไข
    ตอนนี้น่าจะใช้เวลาไม่กี่สัปดาห์หรือหลายเดือนโดยที่อัตราส่วนภาพเชื่อมโยงไปถึงในเบราว์เซอร์ ใน Safari Technical Preview 118 แล้ว ปัจจุบันอยู่เบื้องหลังการตั้งค่าสถานะใน Firefox และ Chrome (ตัวอย่างขนาดใหญ่)

    หากคุณรู้สึกอยากผจญภัย คุณสามารถสับและจัดเรียงสตรีม HTTP/2 ใหม่โดยใช้ผู้ปฏิบัติงาน Edge ซึ่งโดยทั่วไปคือตัวกรองตามเวลาจริงที่อยู่บน CDN เพื่อส่งภาพผ่านเครือข่ายได้เร็วขึ้น ผู้ปฏิบัติงาน Edge ใช้สตรีม JavaScript ที่ใช้ส่วนต่างๆ ที่คุณสามารถควบคุมได้ (โดยทั่วไปคือ JavaScript ที่ทำงานบนขอบ CDN ที่สามารถแก้ไขการตอบสนองการสตรีม) เพื่อให้คุณสามารถควบคุมการส่งภาพได้

    สำหรับพนักงานบริการ มันสายเกินไปเพราะคุณไม่สามารถควบคุมสิ่งที่อยู่ในสายได้ แต่ทำงานได้กับพนักงาน Edge ดังนั้นคุณจึงสามารถใช้ทับไฟล์ JPEG แบบคงที่ที่บันทึกแบบค่อยเป็นค่อยไปสำหรับหน้า Landing Page ใดหน้าหนึ่ง

    สกรีนช็อตของเครื่องมือบรรทัดคำสั่ง Imaging-heap ที่แสดงตารางที่มีขนาดวิวพอร์ตต่างๆ และอัตราส่วนพิกเซลของอุปกรณ์
    เอาต์พุตตัวอย่างโดย Imaging-heap ซึ่งเป็นเครื่องมือบรรทัดคำสั่งที่วัดประสิทธิภาพตามขนาดวิวพอร์ตและอัตราส่วนพิกเซลของอุปกรณ์ (ที่มาของรูปภาพ) (ตัวอย่างขนาดใหญ่)

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

    การเพิ่มประสิทธิภาพเหล่านี้ครอบคลุมเฉพาะพื้นฐานเท่านั้น Addy Osmani ได้เผยแพร่คำแนะนำโดยละเอียดเกี่ยวกับ Essential Image Optimization ซึ่งเจาะลึกลงไปในรายละเอียดของการบีบอัดภาพและการจัดการสี ตัวอย่างเช่น คุณสามารถ เบลอส่วนที่ไม่จำเป็น ของรูปภาพ (โดยใช้ฟิลเตอร์ Gaussian blur กับส่วนเหล่านั้น) เพื่อลดขนาดไฟล์ และในที่สุด คุณอาจเริ่มลบสีหรือเปลี่ยนรูปภาพเป็นขาวดำเพื่อลดขนาดให้ดียิ่งขึ้นไปอีก . สำหรับภาพพื้นหลัง การส่งออกภาพถ่ายจาก Photoshop ที่มีคุณภาพ 0 ถึง 10% ก็เป็นที่ยอมรับได้เช่นกัน

    ใน Smashing Magazine เราใช้ postfix -opt สำหรับชื่อรูปภาพ — ตัวอย่างเช่น brotli-compression-opt.png ; เมื่อใดก็ตามที่รูปภาพมี postfix นั้น ทุกคนในทีมจะรู้ว่ารูปภาพนั้นได้รับการปรับให้เหมาะสมแล้ว

    อ้อ และอย่าใช้ JPEG-XR บนเว็บ — "การประมวลผลการถอดรหัสฝั่งซอฟต์แวร์ JPEG-XR บน CPU ทำให้เป็นโมฆะและมีค่ามากกว่าผลกระทบเชิงบวกที่อาจเกิดขึ้นจากการประหยัดขนาดไบต์ โดยเฉพาะอย่างยิ่งในบริบทของ SPA" (ไม่ใช่ เพื่อผสมกับ Cloudinary / JPEG XL ของ Google)

การแทนที่ GIF แบบเคลื่อนไหวด้วยองค์ประกอบวิดีโอด้วยการประหยัดกว่า 80%
Addy Osmani แนะนำให้แทนที่ GIF แบบเคลื่อนไหวด้วยวิดีโออินไลน์แบบวนซ้ำ ความแตกต่างของขนาดไฟล์นั้นสามารถสังเกตได้ (ประหยัด 80%) (ตัวอย่างขนาดใหญ่)
  1. วิดีโอได้รับการปรับแต่งอย่างเหมาะสมหรือไม่
    เราครอบคลุมรูปภาพแล้ว แต่เราหลีกเลี่ยงการสนทนาเกี่ยวกับ GIF ที่ดี แม้ว่าเราจะรัก GIF แต่ก็ถึงเวลาแล้วที่เราจะทิ้ง GIF เหล่านี้ไปตลอดกาล (อย่างน้อยก็ในเว็บไซต์และแอปของเรา) แทนที่จะโหลด GIF แบบเคลื่อนไหวจำนวนมากซึ่งส่งผลต่อทั้งประสิทธิภาพการเรนเดอร์และแบนด์วิดท์ คุณควรเปลี่ยนไปใช้ WebP แบบเคลื่อนไหว (โดยที่ GIF เป็นตัวสำรอง) หรือแทนที่ด้วยวิดีโอ HTML5 แบบวนซ้ำทั้งหมด

    เบราว์เซอร์ไม่โหลดเนื้อหา <video> ล่วงหน้า แต่วิดีโอ HTML5 มักจะเบากว่าและเล็กกว่า GIF มาก ไม่เหมือนกับรูปภาพ ไม่ใช่ตัวเลือก? อย่างน้อย เราก็สามารถเพิ่มการบีบอัดแบบ lossy ให้กับ GIF ด้วย Lossy GIF, gifsicle หรือ giflossy

    การทดสอบโดย Colin Bendell แสดงให้เห็นว่าวิดีโอแบบอินไลน์ภายในแท็ก img ใน Safari Technology Preview แสดงเร็วกว่าอย่างน้อย 20 เท่า และถอดรหัสเร็วกว่าไฟล์ GIF ที่เทียบเท่ากันถึง 7 เท่า นอกเหนือจากขนาดไฟล์เศษส่วนแล้ว อย่างไรก็ตาม ไม่รองรับในเบราว์เซอร์อื่น

    ในดินแดนแห่งข่าวดี รูปแบบวิดีโอมี ความก้าวหน้าอย่างมาก ในช่วงหลายปีที่ผ่านมา เป็นเวลานาน เราหวังว่า WebM จะกลายเป็นรูปแบบที่ใช้ควบคุมทั้งหมด และ WebP (ซึ่งโดยพื้นฐานแล้วเป็นภาพนิ่งเดียวภายในคอนเทนเนอร์วิดีโอ WebM) จะกลายเป็นรูปแบบแทนที่รูปแบบภาพที่ล้าสมัย อันที่จริงตอนนี้ Safari รองรับ WebP แต่ถึงแม้ WebP และ WebM จะได้รับการสนับสนุนในทุกวันนี้ การพัฒนาก็ไม่ได้เกิดขึ้นจริง

    อย่างไรก็ตาม เราสามารถใช้ WebM สำหรับเบราว์เซอร์ที่ทันสมัยส่วนใหญ่ได้:

    <!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>

    แต่บางทีเราอาจจะทบทวนมันใหม่ทั้งหมด ในปี 2018 Alliance of Open Media ได้เปิดตัวรูปแบบวิดีโอใหม่ที่มีแนวโน้มว่า AV1 AV1 มีการบีบอัดที่คล้ายกับตัวแปลงสัญญาณ H.265 (วิวัฒนาการของ H.264) แต่ AV1 นั้นฟรีไม่เหมือนกับรุ่นหลัง การกำหนดราคาใบอนุญาต H.265 ผลักดันให้ผู้จำหน่ายเบราว์เซอร์เลือกใช้ AV1 ที่มีประสิทธิภาพเทียบเท่าแทน: AV1 (เช่นเดียวกับ H.265) บีบอัดได้ดีเป็นสองเท่าของ WebM

    โลโก้ AV1 2018
    AV1 มีโอกาสสูงที่จะเป็นมาตรฐานสูงสุดสำหรับวิดีโอบนเว็บ (เครดิตรูปภาพ: Wikimedia.org) (ตัวอย่างขนาดใหญ่)

    อันที่จริง ปัจจุบัน Apple ใช้รูปแบบ HEIF และ HEVC (H.265) และรูปภาพและวิดีโอทั้งหมดใน iOS ล่าสุดจะถูกบันทึกในรูปแบบเหล่านี้ ไม่ใช่ JPEG แม้ว่า HEIF และ HEVC (H.265) จะไม่ปรากฏบนเว็บอย่างถูกต้อง (ยัง?) AV1 คือ — และกำลังได้รับการสนับสนุนเบราว์เซอร์ ดังนั้นการเพิ่มแหล่งที่มา AV1 ในแท็ก <video> ของคุณนั้นสมเหตุสมผล เนื่องจากผู้ให้บริการเบราว์เซอร์ทั้งหมดดูเหมือนจะพร้อม

    สำหรับตอนนี้ การเข้ารหัสที่ใช้กันอย่างแพร่หลายและรองรับมากที่สุดคือ H.264 ซึ่งให้บริการโดยไฟล์ MP4 ดังนั้นก่อนให้บริการไฟล์ ตรวจสอบให้แน่ใจว่า MP4 ของคุณได้รับการประมวลผลด้วยการเข้ารหัสหลายทาง เบลอด้วยเอฟเฟกต์ frei0r iirblur (ถ้ามี) และ ข้อมูลเมตาของ moov atom ถูกย้ายไปที่ส่วนหัวของไฟล์ ในขณะที่เซิร์ฟเวอร์ของคุณยอมรับการให้บริการแบบไบต์ Boris Schapira ให้คำแนะนำที่แน่นอนสำหรับ FFmpeg เพื่อเพิ่มประสิทธิภาพวิดีโอให้สูงสุด แน่นอนว่าการจัดหารูปแบบ WebM เป็นทางเลือกก็จะช่วยได้เช่นกัน

    ต้องการเริ่มการเรนเดอร์วิดีโอเร็วขึ้น แต่ ไฟล์วิดีโอยังใหญ่เกินไป ? ตัวอย่างเช่น เมื่อใดก็ตามที่คุณมีวิดีโอพื้นหลังขนาดใหญ่บนหน้า Landing Page? เทคนิคทั่วไปที่จะใช้คือการแสดงเฟรมแรกสุดเป็นภาพนิ่งก่อน หรือแสดงส่วนการวนซ้ำสั้นๆ ที่ปรับให้เหมาะสมอย่างมาก ซึ่งสามารถตีความได้ว่าเป็นส่วนหนึ่งของวิดีโอ จากนั้นเมื่อใดก็ตามที่วิดีโอมีบัฟเฟอร์เพียงพอ ให้เริ่มเล่น วิดีโอที่เกิดขึ้นจริง Doug Sillars ได้เขียนคำแนะนำโดยละเอียดเกี่ยวกับประสิทธิภาพของวิดีโอเบื้องหลังซึ่งอาจเป็นประโยชน์ในกรณีดังกล่าว ( ขอบคุณ Guy Podjarny! )

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

    การวิจัยแสดงให้เห็นว่าคุณภาพการสตรีมวิดีโอส่งผลต่อพฤติกรรมของผู้ดู อันที่จริง ผู้ดูเริ่มละทิ้งวิดีโอหากการหน่วงเวลาเริ่มต้นเกิน 2 วินาที นอกเหนือจากจุดนั้น ความล่าช้าที่เพิ่มขึ้น 1 วินาทีส่งผลให้อัตราการละทิ้งเพิ่มขึ้นประมาณ 5.8% ดังนั้นจึงไม่น่าแปลกใจที่เวลาเริ่มต้นของวิดีโอเฉลี่ยอยู่ที่ 12.8 วินาที โดย 40% ของวิดีโอมีอย่างน้อย 1 แผงลอย และ 20% อย่างน้อย 2 วินาทีของการเล่นวิดีโอที่หยุดนิ่ง ที่จริงแล้ว วิดีโอบน 3G นั้นหลีกเลี่ยงไม่ได้เพราะเล่นวิดีโอได้เร็วกว่าที่เครือข่ายสามารถจัดหาเนื้อหาได้

    แล้วมีทางแก้อย่างไร? โดยปกติอุปกรณ์หน้าจอขนาดเล็กไม่สามารถรองรับ 720p และ 1080p ที่เราให้บริการเดสก์ท็อป ตามที่ Doug Sillars กล่าว เราสามารถสร้างวิดีโอเวอร์ชันที่เล็กกว่า และใช้ Javascript เพื่อตรวจหาแหล่งที่มาสำหรับหน้าจอขนาดเล็กลงเพื่อให้แน่ใจว่าการ เล่นบนอุปกรณ์เหล่านี้รวดเร็วและราบรื่น อีกทางหนึ่ง เราสามารถใช้วิดีโอสตรีมมิ่ง สตรีมวิดีโอ HLS จะส่งวิดีโอที่มีขนาดเหมาะสมไปยังอุปกรณ์ ทำให้ไม่จำเป็นต้องสร้างวิดีโอที่แตกต่างกันสำหรับหน้าจอต่างๆ นอกจากนี้ยังจะเจรจาความเร็วของเครือข่ายและปรับบิตเรตของวิดีโอตามความเร็วของเครือข่ายที่คุณใช้อยู่

    เพื่อหลีกเลี่ยงการสูญเสียแบนด์วิดท์ เราสามารถเพิ่มได้เฉพาะแหล่งวิดีโอสำหรับอุปกรณ์ที่สามารถเล่นวิดีโอได้ดีเท่านั้น อีกวิธีหนึ่ง เราสามารถลบแอตทริบิวต์ autoplay ออกจากแท็ก video ทั้งหมด และใช้ JavaScript เพื่อแทรกการ autoplay สำหรับหน้าจอขนาดใหญ่ นอกจากนี้ เราจำเป็นต้องเพิ่ม preload="none" บน video เพื่อบอกให้เบราว์เซอร์ไม่ดาวน์โหลดไฟล์วิดีโอ ใดๆ จนกว่าจะต้องการไฟล์นั้นจริงๆ:

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    จากนั้น เราสามารถกำหนดเป้าหมายเฉพาะเบราว์เซอร์ที่รองรับ AV1 ได้จริง:

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    จากนั้น เราสามารถเพิ่มการ autoplay อีกครั้งผ่านเกณฑ์ที่กำหนด (เช่น 1000px):

    /* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
    แผนภูมิแท่งแสดง tme (ms) เล็กน้อยตามอุปกรณ์และความเร็วเครือข่าย รวมถึง 3G, เคเบิล, LTE และเนทีฟใน Alcatel 1X, Moto G, Moto G4, MotoE, Nexus 5 และ OnePlus 5
    จำนวนแผงลอยตามอุปกรณ์และความเร็วเครือข่าย อุปกรณ์ที่เร็วกว่าบนเครือข่ายที่เร็วกว่านั้นแทบไม่มีแผงลอยเลย จากการวิจัยของดั๊ก ซิลลาร์ส (ตัวอย่างขนาดใหญ่)

    ประสิทธิภาพการเล่นวิดีโอเป็นเรื่องของตัวมันเอง และหากคุณต้องการเจาะลึกลงไปในรายละเอียด ลองดูซีรีส์อื่นของ Doug Sillars ในเรื่องแนวทางปฏิบัติที่ดีที่สุดสำหรับสถานะปัจจุบันของวิดีโอและการนำส่งวิดีโอที่มีรายละเอียดเกี่ยวกับเมตริกการนำส่งวิดีโอ , การโหลดวิดีโอล่วงหน้า การบีบอัดและการสตรีม สุดท้าย คุณสามารถตรวจสอบว่าการสตรีมวิดีโอของคุณช้าหรือเร็วเพียงใดด้วย Stream or Not

Zach Leatherman's Comprehensive Guide to Font-Loading Strategies แสดงเป็นกราฟแผนที่ความคิด
คู่มือที่ครอบคลุมสำหรับกลยุทธ์การโหลดแบบอักษรของ Zach Leatherman มีตัวเลือกมากมายสำหรับการส่งแบบอักษรเว็บที่ดียิ่งขึ้น
  1. การนำส่งแบบอักษรของเว็บได้รับการปรับให้เหมาะสมหรือไม่
    The first question that's worth asking is if we can get away with using UI system fonts in the first place — we just need to make sure to double check that they appear correctly on various platforms. If it's not the case, chances are high that the web fonts we are serving include glyphs and extra features and weights that aren't being used. We can ask our type foundry to subset web fonts or if we are using open-source fonts, subset them on our own with Glyphhanger or Fontsquirrel. We can even automate our entire workflow with Peter Muller's subfont, a command line tool that statically analyses your page in order to generate the most optimal web font subsets, and then inject them into our pages.

    WOFF2 support is great, and we can use WOFF as fallback for browsers that don't support it — or perhaps legacy browsers could be served system fonts. There are many, many, many options for web font loading, and we can choose one of the strategies from Zach Leatherman's "Comprehensive Guide to Font-Loading Strategies," (code snippets also available as Web font loading recipes).

    Probably the better options to consider today are Critical FOFT with preload and "The Compromise" method. Both of them use a two-stage render for delivering web fonts in steps — first a small supersubset required to render the page fast and accurately with the web font, and then load the rest of the family async. The difference is that "The Compromise" technique loads polyfill asynchronously only if font load events are not supported, so you don't need to load the polyfill by default. Need a quick win? Zach Leatherman has a quick 23-min tutorial and case study to get your fonts in order.

    In general, it might be a good idea to use the preload resource hint to preload fonts, but in your markup include the hints after the link to critical CSS and JavaScript. With preload , there is a puzzle of priorities, so consider injecting rel="preload" elements into the DOM just before the external blocking scripts. According to Andy Davies, "resources injected using a script are hidden from the browser until the script executes, and we can use this behaviour to delay when the browser discovers the preload hint." Otherwise, font loading will cost you in the first render time.

    A screenshot of slide 93 showing two example of images with a title next to them saying ‘Metrics prioritization: preload one of each family’
    When everything is critical, nothing is critical. preload only one or a maximum of two fonts of each family. (Image credit: Zach Leatherman – slide 93) (Large preview)

    It's a good idea to be selective and choose files that matter most, eg the ones that are critical for rendering or that would help you avoiding visible and disruptive text reflows. In general, Zach advises to preload one or two fonts of each family — it also makes sense to delay some font loading if they are less critical.

    It has become quite common to use local() value (which refers to a local font by name) when defining a font-family in the @font-face rule:

     /* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }

    The idea is reasonable: some popular open-source fonts such as Open Sans are coming pre-installed with some drivers or apps, so if the font is available locally, the browser doesn't need to download the web font and can display the local font immediately. As Bram Stein noted, "though a local font matches the name of a web font, it most likely isn't the same font . Many web fonts differ from their "desktop" version. The text might be rendered differently, some characters may fall back to other fonts, OpenType features can be missing entirely, or the line height may be different."

    Also, as typefaces evolve over time, the locally installed version might be very different from the web font, with characters looking very different. So, according to Bram, it's better to never mix locally installed fonts and web fonts in @font-face rules. Google Fonts has followed suit by disabling local() on the CSS results for all users, other than Android requests for Roboto.

    Nobody likes waiting for the content to be displayed. With the font-display CSS descriptor, we can control the font loading behavior and enable content to be readable immediately (with font-display: optional ) or almost immediately (with a timeout of 3s, as long as the font gets successfully downloaded — with font-display: swap ). (Well, it's a bit more complicated than that.)

    However, if you want to minimize the impact of text reflows, we could use the Font Loading API (supported in all modern browsers). Specifically that means for every font, we'd creata a FontFace object, then try to fetch them all, and only then apply them to the page. This way, we group all repaints by loading all fonts asynchronously, and then switch from fallback fonts to the web font exactly once. Take a look at Zach's explanation, starting at 32:15, and the code snippet):

    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));

    To initiate a very early fetch of the fonts with Font Loading API in use, Adrian Bece suggests to add a non-breaking space nbsp; at the top of the body , and hide it visually with aria-visibility: hidden and a .hidden class:

    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>

    This goes along with CSS that has different font families declared for different states of loading, with the change triggered by Font Loading API once the fonts have successfully loaded:

    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }

    If you ever wondered why despite all your optimizations, Lighthouse still suggests to eliminate render-blocking resources (fonts), in the same article Adrian Bece provides a few techniques to make Lighthouse happy, along with a Gatsby Omni Font Loader, a performant asynchronous font loading and Flash Of Unstyled Text (FOUT) handling plugin for Gatsby.

    Now, many of us might be using a CDN or a third-party host to load web fonts from. In general, it's always better to self-host all your static assets if you can, so consider using google-webfonts-helper, a hassle-free way to self-host Google Fonts. And if it's not possible, you can perhaps proxy the Google Font files through the page origin.

    It's worth noting though that Google is doing quite a bit of work out of the box, so a server might need a bit of tweaking to avoid delays ( thanks, Barry! )

    This is quite important especially as since Chrome v86 (released October 2020), cross-site resources like fonts can't be shared on the same CDN anymore — due to the partitioned browser cache. This behavior was a default in Safari for years.

    But if it's not possible at all, there is a way to get to the fastest possible Google Fonts with Harry Roberts' snippet:

    <!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>

    Harry's strategy is to pre-emptively warm up the fonts' origin first. Then we initiate a high-priority, asynchronous fetch for the CSS file. Afterwards, we initiate a low-priority, asynchronous fetch that gets applied to the page only after it's arrived (with a print stylesheet trick). Finally, if JavaScript isn't supported, we fall back to the original method.

    Ah, talking about Google Fonts: you can shave up to 90% of the size of Google Fonts requests by declaring only characters you need with &text . Plus, the support for font-display was added recently to Google Fonts as well, so we can use it out of the box.

    คำเตือนอย่างรวดเร็วแม้ว่า หากคุณใช้ font-display: optional อาจเป็นการด้อยค่าที่จะใช้ preload เนื่องจากจะทริกเกอร์คำขอแบบอักษรของเว็บนั้นก่อน (ทำให้เกิด ความแออัดของเครือข่าย หากคุณมีทรัพยากรพาธที่สำคัญอื่นๆ ที่จำเป็นต้องดึงข้อมูล) ใช้การ preconnect สำหรับคำขอแบบอักษรข้ามต้นทางที่เร็วขึ้น แต่โปรดใช้ความระมัดระวังด้วยการ preload เนื่องจากการโหลดแบบอักษรล่วงหน้าจากแหล่งที่มาอื่นจะทำให้เกิดความขัดแย้งในเครือข่าย เทคนิคทั้งหมดนี้มีอยู่ในสูตรการโหลดแบบอักษรเว็บของ Zach

    ในทางกลับกัน อาจเป็นความคิดที่ดีที่จะเลือกไม่ใช้แบบอักษรของเว็บ (หรืออย่างน้อย การเรนเดอร์ขั้นที่สอง) หากผู้ใช้ได้เปิดใช้งานลดการเคลื่อนไหวในการตั้งค่าการช่วยสำหรับการเข้าถึง หรือได้เลือกใช้ โหมดประหยัดข้อมูล (ดูส่วนหัว Save-Data ) หรือเมื่อผู้ใช้มีการเชื่อมต่อที่ช้า (ผ่าน Network Information API)

    นอกจากนี้เรายังสามารถใช้แบบสอบถามสื่อ CSS ที่ prefers-reduced-data เพื่อ ไม่ ให้กำหนดการประกาศแบบอักษรหากผู้ใช้เลือกใช้โหมดบันทึกข้อมูล (มีกรณีการใช้งานอื่นด้วย) แบบสอบถามสื่อโดยทั่วไปจะเปิดเผยหากส่วนหัวคำขอ Save-Data จากส่วนขยาย Client Hint HTTP เปิด/ปิดเพื่ออนุญาตให้ใช้กับ CSS ปัจจุบันรองรับเฉพาะใน Chrome และ Edge หลังแฟล็ก

    ตัวชี้วัด? ในการวัดประสิทธิภาพการโหลดฟอนต์ของเว็บ ให้พิจารณาเมตริก All Text Visible (ช่วงเวลาที่ฟอนต์ทั้งหมดโหลดและเนื้อหาทั้งหมดแสดงในฟอนต์ของเว็บ), Time to Real Italics และ Web Font Reflow Count หลังจากการเรนเดอร์ครั้งแรก เห็นได้ชัดว่ายิ่งเมตริกทั้งสองมีค่าต่ำเท่าไร ประสิทธิภาพก็จะยิ่งดีขึ้นเท่านั้น

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

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

    ทีนี้ อะไรจะทำให้ กลยุทธ์การโหลดฟอนต์เว็บกันกระสุน ได้? เซ็ตย่อยฟอนต์และเตรียมพวกมันสำหรับการเรนเดอร์ 2 สเตจ ประกาศด้วย font-display คำอธิบาย ใช้ Font Loading API เพื่อจัดกลุ่มการทาสีใหม่และจัดเก็บฟอนต์ในแคชของพนักงานบริการแบบถาวร ในการเข้าชมครั้งแรก ให้ฉีดการโหลดสคริปต์ล่วงหน้าก่อนการบล็อกสคริปต์ภายนอก คุณสามารถถอยกลับไปใช้ Font Face Observer ของ Bram Stein ได้หากจำเป็น และหากคุณสนใจที่จะวัดประสิทธิภาพการโหลดแบบอักษร Andreas Marschke จะสำรวจการติดตามประสิทธิภาพด้วย Font API และ UserTiming API

    สุดท้าย อย่าลืมรวม unicode-range เพื่อแยกแบบอักษรขนาดใหญ่เป็นแบบอักษรเฉพาะภาษาที่มีขนาดเล็กลง และใช้ตัวจับคู่รูปแบบแบบอักษรของ Monica Dinculescu เพื่อลดการเปลี่ยนแปลงที่สั่นสะเทือนในเค้าโครง เนื่องจากความแตกต่างของขนาดระหว่างทางเลือกสำรองและ แบบอักษรเว็บ

    หรือในการจำลองแบบอักษรของเว็บสำหรับแบบอักษรทางเลือก เราสามารถใช้ @font-face descriptors เพื่อแทนที่เมตริกแบบอักษร (ตัวอย่าง เปิดใช้งานใน Chrome 87) (โปรดทราบว่าการปรับเปลี่ยนนั้นซับซ้อนด้วยกองฟอนต์ที่ซับซ้อนแม้ว่า)

    อนาคตดูสดใสหรือไม่? ด้วยการเสริมแต่งฟอนต์แบบโปรเกรสซีฟ ในที่สุดเราอาจสามารถ "ดาวน์โหลดเฉพาะส่วนที่จำเป็นของฟอนต์ในหน้าใดก็ได้ และสำหรับคำขอที่ตามมาสำหรับฟอนต์นั้นเพื่อ 'แก้ไข' การดาวน์โหลดต้นฉบับแบบไดนามิกด้วยชุดสัญลักษณ์เพิ่มเติมตามที่กำหนดในหน้าต่อเนื่อง มุมมอง" ตามที่ Jason Pamental อธิบาย Incremental Transfer Demo พร้อมใช้งานแล้ว และกำลังดำเนินการอยู่

สร้างการเพิ่มประสิทธิภาพ

  1. เราได้กำหนดลำดับความสำคัญของเราหรือไม่?
    เป็นความคิดที่ดีที่จะรู้ว่าคุณกำลังเผชิญกับอะไรก่อน จัดทำ รายการทรัพย์สิน ทั้งหมดของคุณ (JavaScript, รูปภาพ, ฟอนต์, สคริปต์ของบริษัทอื่น และโมดูล "ราคาแพง" บนหน้า เช่น ภาพหมุน, อินโฟกราฟิกที่ซับซ้อน และเนื้อหามัลติมีเดีย) และแบ่งออกเป็นกลุ่ม

    ตั้งค่าสเปรดชีต กำหนดประสบการณ์ หลัก พื้นฐานสำหรับเบราว์เซอร์รุ่นเก่า (เช่น เนื้อหาหลักที่เข้าถึงได้ทั้งหมด) ประสบการณ์ที่ได้รับการ ปรับปรุง สำหรับเบราว์เซอร์ที่มีความสามารถ (เช่น ประสบการณ์ที่สมบูรณ์และสมบูรณ์) และสิ่ง พิเศษ (เนื้อหาที่ไม่จำเป็นจริงๆ และสามารถโหลดแบบ Lazy Loading ได้ เช่น แบบอักษรของเว็บ สไตล์ที่ไม่จำเป็น สคริปต์ภาพหมุน เครื่องเล่นวิดีโอ วิดเจ็ตโซเชียลมีเดีย รูปภาพขนาดใหญ่) หลายปีก่อน เราตีพิมพ์บทความเรื่อง "Improving Smashing Magazine's Performance" ซึ่งอธิบายแนวทางนี้อย่างละเอียด

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

  2. คุณใช้โมดูล JavaScript ดั้งเดิมในการผลิตหรือไม่?
    จำเทคนิคที่ล้ำสมัยที่ดีในการส่งประสบการณ์หลักไปยังเบราว์เซอร์รุ่นเก่าและประสบการณ์ที่ได้รับการปรับปรุงไปยังเบราว์เซอร์สมัยใหม่หรือไม่ เทคนิคที่ปรับปรุงแล้วสามารถใช้ ES2017+ <script type="module"> หรือที่เรียกว่ารูปแบบโมดูล/nomodule (ยังแนะนำโดย Jeremy Wagner ว่าเป็น บริการที่แตกต่างกัน )

    แนวคิดคือการรวบรวมและให้บริการ ชุด JavaScript แยกกันสองชุด : บิลด์ "ปกติ" ชุดหนึ่งที่มี Babel-transforms และ polyfills และให้บริการเฉพาะกับเบราว์เซอร์รุ่นเก่าที่ต้องการจริงๆ และชุดอื่น (ฟังก์ชันเดียวกัน) ที่ไม่มีการแปลงหรือ โพลีฟิล

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

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

    ตัวอย่างที่แสดงวิธีการเลื่อนโมดูล JavaScript ดั้งเดิมโดยค่าเริ่มต้น
    โมดูล Native JavaScript จะถูกเลื่อนออกไปตามค่าเริ่มต้น แทบทุกอย่างเกี่ยวกับโมดูล JavaScript ดั้งเดิม (ตัวอย่างขนาดใหญ่)

    คำเตือนประการหนึ่ง: รูปแบบโมดูล/โมดูล สามารถย้อนกลับได้ในไคลเอนต์บางตัว ดังนั้นคุณอาจต้องการพิจารณาวิธีแก้ปัญหา: รูปแบบการให้บริการส่วนต่างที่มีความเสี่ยงน้อยกว่าของ Jeremy ซึ่งหลีกเลี่ยงเครื่องสแกนพรีโหลด ซึ่งอาจส่งผลต่อประสิทธิภาพในแบบที่อาจไม่ คาดหวัง. ( ขอบคุณเจเรมี! )

    อันที่จริง Rollup รองรับโมดูลในรูปแบบเอาต์พุต ดังนั้นเราจึงสามารถรวมโค้ดและปรับใช้โมดูลในการผลิตได้ Parcel มีการรองรับโมดูลใน Parcel 2 สำหรับ Webpack โมดูล-nomodule-plugin จะสร้างสคริปต์โมดูล/nomodule โดยอัตโนมัติ

    หมายเหตุ : ควรระบุว่าการตรวจหาคุณลักษณะเพียงอย่างเดียวไม่เพียงพอต่อการตัดสินใจอย่างมีข้อมูลเกี่ยวกับเพย์โหลดที่จะจัดส่งไปยังเบราว์เซอร์นั้น ด้วยตัวของมันเอง เราไม่สามารถสรุปความสามารถของอุปกรณ์จากเวอร์ชันของเบราว์เซอร์ได้ ตัวอย่างเช่น โทรศัพท์ Android ราคาถูกในประเทศกำลังพัฒนาส่วนใหญ่ใช้ Chrome และจะตัดมัสตาร์ดแม้ว่าจะมีหน่วยความจำและ CPU ที่จำกัดก็ตาม

    ในที่สุด เมื่อใช้ Device Memory Client Hints Header เราจะสามารถกำหนดเป้าหมายอุปกรณ์ระดับล่างได้อย่างน่าเชื่อถือมากขึ้น ในขณะที่เขียน ส่วนหัวได้รับการสนับสนุนเฉพาะใน Blink (สำหรับคำแนะนำลูกค้าโดยทั่วไป) เนื่องจากหน่วยความจำอุปกรณ์ยังมี JavaScript API ที่มีอยู่ใน Chrome อีกทางเลือกหนึ่งคือการตรวจจับคุณลักษณะตาม API และถอยกลับไปที่ รูปแบบโมดูล/โนโมดูล หากไม่รองรับ ( ขอบคุณ Yoav! )

  3. คุณกำลังใช้การเขย่าต้นไม้ การยกขอบเขต และการแยกรหัสใช่หรือไม่
    Tree-shaking เป็นวิธีการล้างกระบวนการสร้างของคุณโดยการรวมเฉพาะโค้ดที่ใช้จริงในการผลิตและกำจัดการนำเข้าที่ไม่ได้ใช้ใน Webpack เท่านั้น ด้วย Webpack และ Rollup เรายังมี scope hoisting ที่อนุญาตให้เครื่องมือทั้งสองตรวจสอบตำแหน่งที่การโยง import สามารถแบนและแปลงเป็นฟังก์ชัน inline เดียวโดยไม่กระทบต่อโค้ด ด้วย Webpack เราสามารถใช้ JSON Tree Shaking ได้เช่นกัน

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

    พิจารณาใช้ preload-webpack-plugin ที่กำหนดเส้นทางให้คุณแยกโค้ด จากนั้นให้เบราว์เซอร์โหลดล่วงหน้าโดยใช้ <link rel="preload"> หรือ <link rel="prefetch"> คำสั่งอินไลน์ของ Webpack ยังให้การควบคุมการ preload / การ prefetch (ระวังปัญหาการจัดลำดับความสำคัญแม้ว่า)

    จะกำหนดจุดแยกได้ที่ไหน โดยการติดตามว่ามีการใช้ CSS/JavaScript ส่วนใดและไม่ได้ใช้ Umar Hansa อธิบายวิธีที่คุณสามารถใช้ Code Coverage จาก Devtools เพื่อให้บรรลุเป้าหมาย

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

    ดังนั้น วิธีใดดีที่สุดในการแบ่งโค้ดแบบจริงจัง แต่ไม่ก้าวร้าวเกินไปคืออะไร ตามที่ Phil Walton กล่าว "นอกเหนือจากการแยกรหัสผ่านการนำเข้าแบบไดนามิก [เราสามารถ] ใช้ การแยกรหัสที่ระดับแพ็คเกจ โดยที่แต่ละโมดูลโหนดที่นำเข้าจะถูกรวมเข้าด้วยกันตามชื่อแพ็คเกจ" ฟิลมีบทช่วยสอนเกี่ยวกับวิธีการสร้างเช่นกัน

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

    สิ่งที่น่าสนใจอย่างหนึ่งมาจากหัวข้อของ Ivan Akulov ลองนึกภาพว่าคุณมีฟังก์ชันที่คุณเรียกใช้ครั้งเดียว เก็บผลลัพธ์ไว้ในตัวแปร แล้วอย่าใช้ตัวแปรนั้น การเขย่าต้นไม้จะลบตัวแปรออก แต่จะ ไม่ ลบฟังก์ชัน เนื่องจากอาจนำไปใช้อย่างอื่น อย่างไรก็ตาม หากไม่ได้ใช้ฟังก์ชันนี้ในที่ใดๆ คุณอาจต้องการลบออก ในการดำเนินการดังกล่าว ให้เติมฟังก์ชัน /*#__PURE__*/ ซึ่งรองรับโดย Uglify และ Terser ไว้ข้างหน้า เสร็จแล้ว!

    สกรีนช็อตของโค้ด JS ในโปรแกรมแก้ไขที่แสดงวิธีใช้ฟังก์ชัน PURE
    หากต้องการลบฟังก์ชันดังกล่าวเมื่อไม่ได้ใช้ผลลัพธ์ ให้เพิ่มการเรียกฟังก์ชันด้วย /*#__PURE__*/ ผ่าน Ivan Akulov (ตัวอย่างขนาดใหญ่)

    ต่อไปนี้คือเครื่องมืออื่นๆ ที่ Ivan แนะนำ:

    • purgecss-webpack-plugin จะลบคลาสที่ไม่ได้ใช้ โดยเฉพาะเมื่อคุณใช้ Bootstrap หรือ Tailwind
    • เปิดใช้งาน optimization.splitChunks: 'all' พร้อม split-chunks-plugin สิ่งนี้จะทำให้ webpack แยกโค้ดบันเดิลรายการของคุณโดยอัตโนมัติเพื่อการแคชที่ดียิ่งขึ้น
    • ตั้งค่า optimization.runtimeChunk: true สิ่งนี้จะย้ายรันไทม์ของ webpack ไปเป็นส่วนที่แยกจากกัน — และจะปรับปรุงการแคชด้วย
    • google-fonts-webpack-plugin ดาวน์โหลดไฟล์แบบอักษร เพื่อให้คุณสามารถให้บริการจากเซิร์ฟเวอร์ของคุณ
    • workbox-webpack-plugin ช่วยให้คุณสร้างพนักงานบริการด้วยการตั้งค่าแคชล่วงหน้าสำหรับเนื้อหา webpack ทั้งหมดของคุณ นอกจากนี้ ให้ตรวจสอบ Service Worker Packages ซึ่งเป็นคู่มือโมดูลที่ครอบคลุมซึ่งสามารถใช้งานได้ทันที หรือใช้ preload-webpack-plugin เพื่อสร้าง preload / prefetch สำหรับกลุ่ม JavaScript ทั้งหมด
    • speed-measure-webpack-plugin วัดความเร็วของ webpack build ของคุณ โดยให้ข้อมูลเชิงลึกว่าขั้นตอนใดของกระบวนการ build ที่ใช้เวลานานที่สุด
    • ซ้ำ-แพ็คเกจ-checker-webpack-plugin เตือนเมื่อบันเดิลของคุณมีแพ็คเกจเดียวกันหลายเวอร์ชัน
    • ใช้การแยกขอบเขตและย่อชื่อคลาส CSS แบบไดนามิก ณ เวลารวบรวม

สกรีนช็อตของเทอร์มินัลที่แสดงวิธีใช้ webpack loader ชื่อตัวโหลดที่ตอบสนอง เพื่อช่วยคุณสร้างรูปภาพที่ตอบสนองทันที
ความเร็วของรูปภาพคือการแสดงรูปภาพขนาดเล็กลงบนหน้าจอที่เล็กกว่า ด้วยตัวโหลดแบบตอบสนอง โดย Ivan Akulov (ตัวอย่างขนาดใหญ่)
  1. คุณสามารถปิด JavaScript ลงใน Web Worker ได้หรือไม่?
    เพื่อลดผลกระทบต่อ Time-to-Interactive อาจเป็นความคิดที่ดีที่จะลดการโหลด JavaScript จำนวนมากลงใน Web Worker

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

    มีกรณีศึกษาที่น่าสนใจสองสามกรณีเกี่ยวกับผู้ปฏิบัติงานบนเว็บ ซึ่งแสดงแนวทางต่างๆ ของการย้ายเฟรมเวิร์กและตรรกะของแอปแก่ผู้ทำงานบนเว็บ บทสรุป: โดยทั่วไปแล้ว ยังมีความท้าทายอยู่บ้าง แต่มีกรณีการใช้งานที่ดีอยู่แล้ว ( ขอบคุณ Ivan Akulov! )

    เริ่มตั้งแต่ Chrome 80 โหมดใหม่สำหรับผู้ปฏิบัติงานบนเว็บ ที่มีข้อดีด้านประสิทธิภาพของโมดูล JavaScript ถูกจัดส่งไปแล้ว ซึ่งเรียกว่าผู้ปฏิบัติงานโมดูล เราสามารถเปลี่ยนการโหลดสคริปต์และการดำเนินการให้ตรงกับ script type="module" นอกจากนี้เรายังสามารถใช้การนำเข้าแบบไดนามิกสำหรับโค้ดที่โหลดแบบ Lazy Loading โดยไม่ปิดกั้นการทำงานของผู้ปฏิบัติงาน

    เริ่มต้นอย่างไร? ต่อไปนี้คือแหล่งข้อมูลบางส่วนที่ควรค่าแก่การพิจารณา:

    • Surma ได้เผยแพร่คำแนะนำที่ยอดเยี่ยมเกี่ยวกับวิธีการเรียกใช้ JavaScript จากเธรดหลักของเบราว์เซอร์ และเมื่อใดที่คุณควรใช้ Web Workers
    • ตรวจสอบการพูดคุยของ Surma เกี่ยวกับสถาปัตยกรรมเธรดหลัก
    • ภารกิจเพื่อรับประกันการตอบสนองโดย Shubhie Panicker และ Jason Miller ให้ข้อมูลเชิงลึกโดยละเอียดเกี่ยวกับวิธีใช้ผู้ปฏิบัติงานบนเว็บ และเมื่อใดควรหลีกเลี่ยง
    • การหลีกหนีจากวิถีผู้ใช้: Less Jank With Web Workers เน้นรูปแบบที่เป็นประโยชน์สำหรับการทำงานกับ Web Workers วิธีที่มีประสิทธิภาพในการสื่อสารระหว่างผู้ปฏิบัติงาน จัดการการประมวลผลข้อมูลที่ซับซ้อนจากเธรดหลัก และทดสอบและแก้ไขข้อบกพร่อง
    • Workerize อนุญาตให้คุณย้ายโมดูลไปยัง Web Worker โดยจะแสดงฟังก์ชันที่ส่งออกเป็นพร็อกซีแบบอะซิงโครนัสโดยอัตโนมัติ
    • หากคุณกำลังใช้ Webpack คุณสามารถใช้ workerize-loader หรือคุณสามารถใช้ปลั๊กอินผู้ปฏิบัติงานได้เช่นกัน
    รหัสใน DOM แสดงทางด้านซ้ายเป็นตัวอย่างของสิ่งที่ควรใช้และหลีกเลี่ยงเมื่อใช้ Web Worker
    ใช้ผู้ปฏิบัติงานบนเว็บเมื่อโค้ดถูกบล็อกเป็นเวลานาน แต่ให้หลีกเลี่ยงเมื่อคุณพึ่งพา DOM จัดการกับการตอบสนองอินพุต และต้องการความล่าช้าน้อยที่สุด (ผ่าน Addy Osmani) (ตัวอย่างขนาดใหญ่)

    โปรดทราบว่า Web Workers ไม่มีสิทธิ์เข้าถึง DOM เนื่องจาก DOM ไม่ "ปลอดภัยสำหรับเธรด" และโค้ดที่เรียกใช้งานจะต้องมีอยู่ในไฟล์แยกต่างหาก

  2. คุณสามารถถ่าย "เส้นทางลัด" ไปยัง WebAssembly ได้หรือไม่
    เราสามารถถ่ายโอนงานหนักทางคอมพิวเตอร์ออกไปที่ WebAssembly ( WASM ) ซึ่งเป็นรูปแบบคำสั่งไบนารี ซึ่งออกแบบให้เป็นเป้าหมายแบบพกพาสำหรับการรวบรวมภาษาระดับสูง เช่น C/C++/Rust การสนับสนุนเบราว์เซอร์มีความโดดเด่น และเมื่อเร็ว ๆ นี้สามารถใช้งานได้เนื่องจากการเรียกใช้ฟังก์ชันระหว่าง JavaScript และ WASM เริ่มเร็วขึ้น นอกจากนี้ยังรองรับบน Edge Cloud ของ Fastly

    แน่นอน WebAssembly ไม่ควรมาแทนที่ JavaScript แต่มันสามารถเสริมได้ในกรณีที่คุณสังเกตเห็นว่า CPU hogs สำหรับเว็บแอปส่วนใหญ่ JavaScript เหมาะสมกว่า และ WebAssembly เหมาะที่สุดสำหรับ เว็บแอป ที่ต้องใช้การประมวลผลสูง เช่น เกม

    หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ WebAssembly:

    • Lin Clark ได้เขียนซีรีส์อย่างละเอียดเกี่ยวกับ WebAssembly และ Milica Mihajlija ให้ภาพรวมทั่วไปเกี่ยวกับวิธีการเรียกใช้โค้ดเนทีฟในเบราว์เซอร์ เหตุใดคุณจึงอาจต้องการทำเช่นนั้น และความหมายของ JavaScript และอนาคตของการพัฒนาเว็บทั้งหมดมีความหมายอย่างไร
    • วิธีที่เราใช้ WebAssembly เพื่อเพิ่มความเร็วให้กับเว็บแอปของเราได้ถึง 20 เท่า (กรณีศึกษา) จะเน้นที่กรณีศึกษาว่าการคำนวณ JavaScript ที่ช้านั้นถูกแทนที่ด้วย WebAssembly ที่คอมไพล์แล้วอย่างไร และปรับปรุงประสิทธิภาพอย่างมีนัยสำคัญ
    • Patrick Hamann พูดถึงบทบาทที่เพิ่มขึ้นของ WebAssembly และเขากำลังหักล้างตำนานบางอย่างเกี่ยวกับ WebAssembly สำรวจความท้าทายต่างๆ และเราสามารถใช้งานได้จริงในแอปพลิเคชันในปัจจุบัน
    • Google Codelabs ให้ข้อมูลเบื้องต้นเกี่ยวกับ WebAssembly ซึ่งเป็นหลักสูตร 60 นาทีที่คุณจะได้เรียนรู้วิธีการนำโค้ดเนทีฟในภาษา C และคอมไพล์ไปยัง WebAssembly แล้วเรียกใช้โดยตรงจาก JavaScript
    • Alex Danilo ได้อธิบาย WebAssembly และวิธีการทำงานในการพูดคุย Google I/O ของเขา นอกจากนี้ Benedek Gagyi ยังได้แบ่งปันกรณีศึกษาเชิงปฏิบัติเกี่ยวกับ WebAssembly โดยเฉพาะวิธีที่ทีมใช้เป็นรูปแบบเอาต์พุตสำหรับ C++ codebase ของพวกเขาไปยัง iOS, Android และเว็บไซต์

    ยังไม่แน่ใจว่า เมื่อใดควรใช้ Web Workers, Web Assembly, สตรีม หรือบางที WebGL JavaScript API เพื่อเข้าถึง GPU การเร่ง JavaScript เป็นคำแนะนำสั้นๆ แต่มีประโยชน์ ซึ่งจะอธิบายว่าเมื่อใดควรใช้อะไรและเพราะเหตุใด พร้อมด้วยผังงานที่มีประโยชน์และทรัพยากรที่มีประโยชน์มากมาย

ภาพประกอบของ C++, C หรือ Rust ที่แสดงทางด้านซ้ายพร้อมลูกศรแสดงไปยังเบราว์เซอร์ที่มีไบนารี WASM ที่เพิ่มลงใน JavaScript, CSS และ HTML
Milica Mihajlija ให้ภาพรวมทั่วไปเกี่ยวกับวิธีการทำงานของ WebAssembly และเหตุใดจึงมีประโยชน์ (ตัวอย่างขนาดใหญ่)
  1. เราให้บริการรหัสดั้งเดิมกับเบราว์เซอร์รุ่นเก่าเท่านั้นหรือไม่
    เนื่องจาก ES2017 ได้รับการสนับสนุนเป็นอย่างดีในเบราว์เซอร์สมัยใหม่ เราจึงสามารถใช้ babelEsmPlugin เพื่อ transpile เฉพาะคุณลักษณะ ES2017+ ที่เบราว์เซอร์รุ่นใหม่ที่คุณกำหนดเป้าหมายไม่รองรับ

    Houssein Djirdeh และ Jason Miller ได้เผยแพร่คู่มือที่ครอบคลุมเกี่ยวกับวิธีการ transpile และให้บริการ JavaScript ที่ทันสมัยและดั้งเดิม โดยจะลงรายละเอียดเกี่ยวกับการทำให้มันทำงานกับ Webpack และ Rollup และเครื่องมือที่จำเป็น คุณยังสามารถประมาณจำนวน JavaScript ที่คุณสามารถกำจัดบนไซต์หรือ App Bundle ของคุณได้

    โมดูล JavaScript ได้รับการสนับสนุนในเบราว์เซอร์หลักทั้งหมด ดังนั้นให้ใช้ script type="module" เพื่อให้เบราว์เซอร์ที่รองรับโมดูล ES โหลดไฟล์ ในขณะที่เบราว์เซอร์รุ่นเก่าสามารถโหลดบิลด์ดั้งเดิมด้วย script nomodule

    ทุกวันนี้ เราสามารถเขียน JavaScript แบบโมดูลซึ่งทำงานแบบเนทีฟในเบราว์เซอร์ โดยไม่ต้องใช้ทรานสปิลเดอร์หรือบันเดิล <link rel="modulepreload"> ส่วนหัวเป็นวิธีการเริ่มต้นการโหลดสคริปต์โมดูลก่อน (และมีความสำคัญสูง) โดยพื้นฐานแล้ว มันเป็นวิธีที่ดีในการช่วยเพิ่มการใช้แบนด์วิดท์สูงสุด โดยบอกเบราว์เซอร์เกี่ยวกับสิ่งที่ต้องดึงข้อมูล เพื่อไม่ให้ติดขัดกับสิ่งที่ต้องทำในระหว่างการเดินทางไปกลับที่ยาวนานเหล่านั้น นอกจากนี้ Jake Archibald ยังได้ตีพิมพ์บทความที่มีรายละเอียดเกี่ยวกับ gotchas และสิ่งที่ควรคำนึงถึงด้วย ES Modules ที่ควรค่าแก่การอ่าน

สคริปต์อินไลน์จะถูกเลื่อนออกไปจนกว่าจะมีการบล็อกสคริปต์ภายนอกและสคริปต์อินไลน์
Jake Archibald ได้ตีพิมพ์บทความที่มีรายละเอียดเกี่ยวกับ gotchas และสิ่งที่ต้องคำนึงถึงเกี่ยวกับโมดูล ES เช่น สคริปต์อินไลน์จะถูกเลื่อนออกไปจนกว่าจะมีการบล็อกสคริปต์ภายนอกและสคริปต์แบบอินไลน์ (ตัวอย่างขนาดใหญ่)
  1. ระบุและเขียนโค้ดเดิมใหม่ด้วยการแยกส่วนที่เพิ่มขึ้น
    โครงการที่มีอายุการใช้งานยาวนานมีแนวโน้มที่จะรวบรวมฝุ่นและรหัสที่ล้าสมัย ทบทวนการพึ่งพาของคุณและประเมินว่าต้องใช้เวลาเท่าใดในการปรับโครงสร้างใหม่หรือเขียนโค้ดเดิมที่ก่อให้เกิดปัญหาขึ้นใหม่เมื่อเร็วๆ นี้ แน่นอนว่าเป็นงานใหญ่เสมอ แต่เมื่อคุณทราบผลกระทบของโค้ดเดิมแล้ว คุณสามารถเริ่มต้นด้วยการแยกส่วนที่เพิ่มขึ้นได้

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

  2. ระบุและลบ CSS/JS ที่ไม่ได้ใช้
    ความครอบคลุมของโค้ด CSS และ JavaScript ใน Chrome ช่วยให้คุณเรียนรู้ว่าโค้ดใดถูกเรียกใช้/นำไปใช้ และโค้ดใดยังไม่ได้ดำเนินการ คุณสามารถเริ่มบันทึกความครอบคลุม ดำเนินการบนเพจ แล้วสำรวจผลลัพธ์ความครอบคลุมของโค้ดได้ เมื่อคุณตรวจพบโค้ดที่ไม่ได้ใช้แล้ว ให้ค้นหาโมดูลเหล่านั้นและ lazy load ด้วย import() (ดูทั้งเธรด) จากนั้นทำซ้ำโปรไฟล์ความครอบคลุมและตรวจสอบว่าขณะนี้มีการจัดส่งรหัสน้อยลงในการโหลดครั้งแรก

    คุณสามารถใช้ Puppeteer เพื่อรวบรวมการครอบคลุมโค้ดโดยทางโปรแกรม Chrome ให้คุณส่งออกผลลัพธ์การครอบคลุมโค้ดได้เช่นกัน ดังที่ Andy Davies ระบุไว้ คุณอาจต้องการรวบรวมความครอบคลุมของโค้ดสำหรับเบราว์เซอร์ทั้งรุ่นใหม่และรุ่นเก่า

    มีกรณีการใช้งานและเครื่องมืออื่นๆ มากมายสำหรับ Puppetter ที่อาจต้องการการเปิดเผยเพิ่มเติมอีกเล็กน้อย:

    • กรณีการใช้งานสำหรับ Puppeteer เช่น การแยกภาพอัตโนมัติหรือการตรวจสอบ CSS ที่ไม่ได้ใช้กับทุกบิลด์
    • สูตรประสิทธิภาพเว็บด้วย Puppeteer
    • เครื่องมือที่มีประโยชน์สำหรับการบันทึกและสร้างสคริปต์ Pupeeteer และนักเขียนบทละคร
    • นอกจากนี้ คุณยังสามารถบันทึกการทดสอบได้ใน DevTools
    • ภาพรวมของ Puppeteer โดย Nitay Neeman พร้อมตัวอย่างและกรณีการใช้งาน
    ภาพหน้าจอของ Pupeteer Recorder ทางด้านซ้าย และภาพหน้าจอ Puppeteer Sandbox ที่แสดงทางด้านขวา
    เราสามารถใช้ Puppeteer Recorder และ Puppeteer Sandbox เพื่อบันทึกการโต้ตอบของเบราว์เซอร์และสร้างสคริปต์ Puppeteer และ Playwright (ตัวอย่างขนาดใหญ่)

    นอกจากนี้ purgecss, UnCSS และ Helium สามารถช่วยคุณลบสไตล์ที่ไม่ได้ใช้ออกจาก CSS และหากคุณไม่แน่ใจว่ามีการใช้โค้ดที่น่าสงสัยในที่ใดที่หนึ่งหรือไม่ คุณสามารถทำตามคำแนะนำของ Harry Roberts: สร้าง GIF แบบโปร่งใสขนาด 1×1px สำหรับคลาสใดคลาสหนึ่งแล้ววางลงในไดเร็กทอรี dead/ เช่น /assets/img/dead/comments.gif .

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

    สำหรับแผนก I-feel-adventurous คุณสามารถทำให้การรวบรวม CSS ที่ไม่ได้ใช้โดยอัตโนมัติผ่านชุดของเพจโดยการตรวจสอบ DevTools โดยใช้ DevTools

ตารางเปรียบเทียบ Webpack
ในบทความของเขา Benedikt Rotsch แสดงให้เห็นว่าการเปลี่ยนจาก Moment.js เป็น date-fns สามารถโกนได้ประมาณ 300 มิลลิวินาทีสำหรับการระบายสีครั้งแรกบน 3G และโทรศัพท์มือถือระดับล่าง (ตัวอย่างขนาดใหญ่)
  1. ตัดขนาดกลุ่ม JavaScript ของคุณ
    ตามที่ Addy Osmani ระบุไว้ มีโอกาสสูงที่คุณจะจัดส่งไลบรารี JavaScript แบบเต็มเมื่อคุณต้องการเพียงเศษส่วน พร้อมกับโพลีฟิลที่ลงวันที่สำหรับเบราว์เซอร์ที่ไม่ต้องการหรือเพียงแค่โค้ดที่ซ้ำกัน เพื่อหลีกเลี่ยงโอเวอร์เฮด ให้ลองใช้ webpack-libs-optimizations ที่ลบเมธอดและ polyfills ที่ไม่ได้ใช้ระหว่างกระบวนการสร้าง

    ตรวจสอบและตรวจทาน polyfills ที่คุณส่งไปยังเบราว์เซอร์รุ่นเก่าและเบราว์เซอร์รุ่นใหม่ และตั้งกลยุทธ์ให้มากขึ้น ดูที่ polyfill.io ซึ่งเป็นบริการที่ยอมรับคำขอสำหรับชุดคุณลักษณะของเบราว์เซอร์และส่งคืนเฉพาะ polyfill ที่เบราว์เซอร์ที่ร้องขอต้องการ

    เพิ่มการ ตรวจสอบบันเดิ ลลงในเวิร์กโฟลว์ปกติของคุณด้วย อาจมีทางเลือกอื่นที่มีน้ำหนักเบาสำหรับไลบรารีหนักที่คุณเพิ่มเมื่อหลายปีก่อน เช่น Moment.js (เลิกใช้งานแล้ว) อาจถูกแทนที่ด้วย:

    • API การทำให้เป็นสากลดั้งเดิม
    • Day.js พร้อม Moment.js API และรูปแบบที่คุ้นเคย
    • date-fns หรือ
    • ลุกซอน.
    • คุณยังสามารถใช้ Skypack Discover ที่รวมคำแนะนำแพ็คเกจที่ตรวจสอบโดยเจ้าหน้าที่เข้ากับการค้นหาที่เน้นคุณภาพ

    การวิจัยของ Benedikt Rotsch แสดงให้เห็นว่าการเปลี่ยนจาก Moment.js เป็น date-fns สามารถโกนได้ประมาณ 300 มิลลิวินาทีสำหรับการระบายสีครั้งแรกบน 3G และโทรศัพท์มือถือระดับล่าง

    สำหรับการตรวจสอบบันเดิล Bundlephobia สามารถช่วยค้นหาค่าใช้จ่ายในการเพิ่มแพ็คเกจ npm ให้กับบันเดิลของคุณได้ size-limit ขยายการตรวจสอบขนาดบันเดิลพื้นฐานพร้อมรายละเอียดเกี่ยวกับเวลาดำเนินการ JavaScript คุณยังสามารถรวมค่าใช้จ่ายเหล่านี้กับ Lighthouse Custom Audit ได้อีกด้วย สิ่งนี้ใช้ได้กับกรอบงานด้วย โดยการถอดหรือตัดแต่ง Vue MDC Adapter (Material Components for Vue) สไตล์จะลดลงจาก 194KB เป็น 10KB

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

    • webpack-bundle-analyzer
    • Source Map Explorer
    • Bundle Buddy
    • Bundlefobia
    • การวิเคราะห์ Webpack แสดงให้เห็นว่าเหตุใดจึงรวมโมดูลเฉพาะไว้ในบันเดิล
    • Bundle-wizard ยังสร้างแผนที่ของการพึ่งพาสำหรับทั้งหน้า
    • ปลั๊กอินขนาด Webpack
    • นำเข้าต้นทุนสำหรับ Visual Code

    คุณสามารถตัดแต่งเฟรมเวิร์กและคอมไพล์เป็น บันเดิล JavaScript ดิบ ที่ไม่ต้องการโค้ดเพิ่มเติมอีกทางเลือกหนึ่งสำหรับการจัดส่งเฟรมเวิร์กทั้งหมด Svelte ทำได้ และปลั๊กอิน Rawact Babel ก็เช่นกัน ซึ่งจะแปลงส่วนประกอบ React.js ไปยังการดำเนินการ DOM ดั้งเดิม ณ เวลาบิลด์ ทำไม? ตามที่ผู้ดูแลอธิบาย "react-dom มีโค้ดสำหรับทุกองค์ประกอบที่เป็นไปได้/HTMLElement ที่สามารถแสดงผลได้ รวมถึงโค้ดสำหรับการแสดงผลส่วนเพิ่ม การจัดตารางเวลา การจัดการเหตุการณ์ ฯลฯ แต่มีแอปพลิเคชันที่ไม่ต้องการคุณลักษณะเหล่านี้ทั้งหมด (ในตอนแรก การโหลดหน้า) สำหรับแอปพลิเคชันดังกล่าว การใช้การดำเนินการ DOM ดั้งเดิมเพื่อสร้างอินเทอร์เฟซผู้ใช้แบบโต้ตอบอาจสมเหตุสมผล"

size-limit ให้การตรวจสอบขนาดบันเดิลพื้นฐานพร้อมรายละเอียดเกี่ยวกับเวลาดำเนินการ JavaScript ด้วย
size-limit ให้การตรวจสอบขนาดบันเดิลพื้นฐานพร้อมรายละเอียดเกี่ยวกับเวลาดำเนินการ JavaScript เช่นกัน (ตัวอย่างขนาดใหญ่)
  1. เราใช้ความชุ่มชื้นบางส่วนหรือไม่?
    ด้วยจำนวน JavaScript ที่ใช้ในแอปพลิเคชัน เราจำเป็นต้องหาวิธีส่งไปยังไคลเอนต์ให้น้อยที่สุด วิธีหนึ่งในการทำเช่นนั้น — และเราได้อธิบายคร่าวๆ แล้ว — คือการให้น้ำบางส่วน แนวคิดนี้ค่อนข้างง่าย: แทนที่จะทำ SSR แล้วส่งแอปทั้งหมดไปยังไคลเอ็นต์ เฉพาะ JavaScript ของแอปเพียงเล็กน้อยเท่านั้นที่จะถูกส่งไปยังไคลเอ็นต์แล้วจึงไฮเดรท เราสามารถคิดว่ามันเป็นแอพ React ขนาดเล็กหลายตัวที่มีรูทการเรนเดอร์หลายตัวบนเว็บไซต์แบบคงที่

    ในบทความ "กรณีการให้น้ำบางส่วน (ด้วย Next และ Preact)" Lukas Bombach อธิบายว่าทีมที่อยู่เบื้องหลัง Welt.de ซึ่งเป็นหนึ่งในร้านข่าวในเยอรมนีมีประสิทธิภาพที่ดีขึ้นด้วยการให้น้ำบางส่วนได้อย่างไร คุณยังตรวจสอบ GitHub repo ที่มีประสิทธิภาพสูงได้ด้วยคำอธิบายและข้อมูลโค้ด

    คุณยังสามารถพิจารณาทางเลือกอื่น:

    • การให้ความชุ่มชื้นบางส่วนด้วย Preact และ Eleventy
    • การให้ความชุ่มชื้นแบบก้าวหน้าใน React GitHub repo
    • ความชุ่มชื้นใน Vue.js (GitHub repo)
    • นำเข้าในรูปแบบการโต้ตอบเพื่อโหลดทรัพยากรที่ไม่สำคัญ (เช่น ส่วนประกอบ การฝัง) เมื่อผู้ใช้โต้ตอบกับ UI ที่ต้องการ

    Jason Miller ได้เผยแพร่ตัวอย่างการทำงานเกี่ยวกับวิธีการใช้ไฮเดรชั่นแบบก้าวหน้าด้วย React เพื่อให้คุณสามารถใช้งานได้ทันที: การสาธิต 1 การสาธิต 2 การสาธิต 3 (มีอยู่ใน GitHub ด้วย) นอกจากนี้ คุณยังสามารถดูไลบรารีส่วนประกอบที่แสดงผลล่วงหน้าได้

    +485KB ของ JavaScript เมื่อ loadshare() ใน Google Docs
    การนำเข้าในการโต้ตอบสำหรับโค้ดของบุคคลที่หนึ่งควรทำได้ก็ต่อเมื่อคุณไม่สามารถดึงทรัพยากรล่วงหน้าก่อนการโต้ตอบได้ (ตัวอย่างขนาดใหญ่)
  2. เราได้ปรับกลยุทธ์สำหรับ React/SPA ให้เหมาะสมแล้วหรือยัง?
    กำลังดิ้นรนกับประสิทธิภาพในแอปพลิเคชันหน้าเดียวใช่หรือไม่ Jeremy Wagner ได้สำรวจผลกระทบของประสิทธิภาพการทำงานของเฟรมเวิร์กฝั่งไคลเอ็นต์บนอุปกรณ์ที่หลากหลาย โดยเน้นถึงความหมายและหลักเกณฑ์บางประการที่เราอาจต้องการทราบเมื่อใช้อุปกรณ์ดังกล่าว

    ด้วยเหตุนี้ นี่คือกลยุทธ์ SPA ที่ Jeremy แนะนำให้ใช้สำหรับเฟรมเวิร์ก React (แต่ไม่ควรเปลี่ยนแปลงอย่างมากสำหรับเฟรมเวิร์กอื่นๆ):

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

    มีกลยุทธ์อื่นๆ สองสามอย่างที่คุณอาจต้องการติดตามหรือทบทวน:

    • ข้อควรพิจารณาด้านประสิทธิภาพสำหรับ CSS-in-JS ในแอป React
    • ลดขนาดบันเดิล Next.js โดยการโหลดโพลีฟิลเมื่อจำเป็นเท่านั้น โดยใช้การนำเข้าแบบไดนามิกและการให้ความชุ่มชื้นแบบสันหลังยาว
    • ความลับของ JavaScript: เรื่องราวของ React, Performance Optimization และ Multi-threading, ซีรีส์ยาว 7 ตอนในการปรับปรุงความท้าทายของอินเทอร์เฟซผู้ใช้ด้วย React,
    • วิธีวัดประสิทธิภาพ React และวิธีกำหนดโปรไฟล์แอปพลิเคชัน React
    • การสร้างแอนิเมชั่นเว็บสำหรับมือถือเป็นอันดับแรกใน React การพูดคุยที่ยอดเยี่ยมโดย Alex Holachek พร้อมด้วยสไลด์และ GitHub repo ( ขอบคุณสำหรับเคล็ดลับ Addy! )
    • webpack-libs-optimizations เป็น GitHub repo ที่ยอดเยี่ยมพร้อมการปรับแต่งประสิทธิภาพที่เกี่ยวข้องกับ Webpack โดยเฉพาะที่มีประโยชน์มากมาย ดูแลโดย Ivan Akulov
    • ตอบสนองการปรับปรุงประสิทธิภาพใน Notion ซึ่งเป็นแนวทางโดย Ivan Akulov เกี่ยวกับวิธีการปรับปรุงประสิทธิภาพใน React พร้อมคำแนะนำที่มีประโยชน์มากมายเพื่อทำให้แอปเร็วขึ้นประมาณ 30%
    • React Refresh Webpack Plugin (ทดลอง) ช่วยให้สามารถรีโหลดใหม่ได้ โดยจะคงสถานะส่วนประกอบไว้ และรองรับ hook และส่วนประกอบฟังก์ชัน
    • ระวัง React Server Components ขนาด Zero-bundle ซึ่งเป็นส่วนประกอบประเภทใหม่ที่เสนอซึ่งจะไม่มีผลกระทบต่อขนาดบันเดิล ขณะนี้โครงการอยู่ในระหว่างการพัฒนา แต่ข้อเสนอแนะใด ๆ จากชุมชนนั้นน่าชื่นชมมาก (ผู้อธิบายที่ยอดเยี่ยมโดย Sophie Alpert)
  3. คุณกำลังใช้การดึงข้อมูลล่วงหน้าสำหรับชิ้นส่วน JavaScript หรือไม่
    เราสามารถใช้ heuristics เพื่อตัดสินใจว่าจะโหลดกลุ่ม JavaScript ล่วงหน้าเมื่อใด Guess.js คือชุดเครื่องมือและไลบรารีที่ใช้ข้อมูล Google Analytics เพื่อกำหนดว่าหน้าใดที่ผู้ใช้ น่าจะเข้าชมมากที่สุดต่อ จากหน้าที่กำหนด ตามรูปแบบการนำทางของผู้ใช้ที่รวบรวมจาก Google Analytics หรือแหล่งข้อมูลอื่นๆ Guess.js สร้างโมเดลการเรียนรู้ด้วยเครื่องเพื่อคาดการณ์และดึงข้อมูล JavaScript ล่วงหน้าซึ่งจำเป็นในหน้าถัดไปแต่ละหน้า

    ดังนั้น ทุกองค์ประกอบเชิงโต้ตอบจะได้รับคะแนนความน่าจะเป็นสำหรับการมีส่วนร่วม และจากคะแนนนั้น สคริปต์ฝั่งไคลเอ็นต์จึงตัดสินใจดึงทรัพยากรล่วงหน้าล่วงหน้า คุณสามารถรวมเทคนิคนี้เข้ากับแอปพลิเคชัน Next.js, Angular และ React ได้ และยังมีปลั๊กอิน Webpack ที่ทำให้กระบวนการตั้งค่าเป็นไปโดยอัตโนมัติอีกด้วย

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

    ต้องการสิ่งที่ซับซ้อนน้อยกว่าหรือไม่? DNStradamus ทำการดึงข้อมูล DNS ล่วงหน้าสำหรับลิงก์ขาออกตามที่ปรากฏในวิวพอร์ต Quicklink, InstantClick และ Instant.page เป็นไลบรารีขนาดเล็กที่ ดึงข้อมูลลิงก์ล่วงหน้าในวิวพอร์ตโดยอัตโนมัติ ในช่วงเวลาว่างเพื่อพยายามทำให้การนำทางในหน้าถัดไปโหลดเร็วขึ้น Quicklink อนุญาตให้ดึงเส้นทาง React Router และ Javascript ล่วงหน้า แถมยังคำนึงถึงข้อมูลด้วย ดังนั้นจึงไม่ดึงข้อมูลล่วงหน้าบน 2G หรือ Data-Saver อินเทอร์เน็ตอยู่ เช่นเดียวกับ Instant.page หากโหมดถูกตั้งค่าให้ใช้การ ดึงข้อมูลล่วงหน้าของวิวพอร์ต (ซึ่งเป็นค่าเริ่มต้น)

    หากคุณต้องการดูศาสตร์ของการดึงข้อมูลล่วงหน้าเชิงทำนายอย่างละเอียด Divya Tagtachian มีการพูดคุยที่ยอดเยี่ยมเกี่ยวกับศิลปะแห่งการทำนายล่วงหน้า ซึ่งครอบคลุมตัวเลือกทั้งหมดตั้งแต่ต้นจนจบ

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

    การสตรีมสคริปต์ช่วยให้แยกวิเคราะห์สคริปต์ async หรือ defer scripts บนเธรดพื้นหลังแยกต่างหากเมื่อการดาวน์โหลดเริ่มต้นขึ้น ดังนั้น ในบางกรณีจะช่วยปรับปรุงเวลาในการโหลดหน้าเว็บได้มากถึง 10% Practically, use <script defer> in the <head> , so that the browsers can discover the resource early and then parse it on the background thread.

    Caveat : Opera Mini doesn't support script deferment, so if you are developing for India or Africa, defer will be ignored, resulting in blocking rendering until the script has been evaluated (thanks Jeremy!) .

    You could also hook into V8's code caching as well, by splitting out libraries from code using them, or the other way around, merge libraries and their uses into a single script, group small files together and avoid inline scripts. Or perhaps even use v8-compile-cache.

    When it comes to JavaScript in general, there are also some practices that are worth keeping in mind:

    • Clean Code concepts for JavaScript, a large collection of patterns for writing readable, reusable, and refactorable code.
    • You can Compress data from JavaScript with the CompressionStream API, eg to gzip before uploading data (Chrome 80+).
    • Detached window memory leaks and Fixing memory leaks in web apps are detailed guides on how to find and fix tricky JavaScript memory leaks. Plus, you can use queryObjects(SomeConstructor) from the DevTools Console ( thanks, Mathias! ).
    • Reexports are bad for loading and runtime performance, and avoiding them can help reduce the bundle size significantly.
    • We can improve scroll performance with passive event listeners by setting a flag in the options parameter. So browsers can scroll the page immediately, rather than after the listener has finished. (via Kayce Basques).
    • If you have any scroll or touch* listeners, pass passive: true to addEventListener. This tells the browser you're not planning to call event.preventDefault() inside, so it can optimize the way it handles these events. (via Ivan Akulov)
    • We can achieve better JavaScript scheduling with isInputPending(), a new API that attempts to bridge the gap between loading and responsiveness with the concepts of interrupts for user inputs on the web, and allows for JavaScript to be able to check for input without yielding to the browser.
    • You can also automatically remove an event listener after it has executed.
    • Firefox's recently released Warp, a significant update to SpiderMonkey (shipped in Firefox 83), Baseline Interpreter and there are a few JIT Optimization Strategies available as well.
An illustration to help you understand time loading and responsiveness
A blue banner showing running JS with white lines in regular gaps representing the time when we proactively check whether there’s user input without incurring the overhead of yielding execution to the browser and back
isInputPending() is a new browser API that attempts to bridge the gap between loading and responsiveness.(Large preview)
An illustration of a map showing the chain of each request to different domains, all the way to eighth-party scripts
The request map for CNN.com showing the chain of each request to different domains, all the way to eighth-party scripts. แหล่งที่มา. (ตัวอย่างขนาดใหญ่)
  1. Always prefer to self-host third-party assets.
    Yet again, self-host your static assets by default. It's common to assume that if many sites use the same public CDN and the same version of a JavaScript library or a web font, then the visitors would land on our site with the scripts and fonts already cached in their browser, speeding up their experience considerably. However, it's very unlikely to happen.

    For security reasons, to avoid fingerprinting, browsers have been implementing partitioned caching that was introduced in Safari back in 2013, and in Chrome last year. So if two sites point to the exact same third-party resource URL, the code is downloaded once per domain , and the cache is "sandboxed" to that domain due to privacy implications ( thanks, David Calhoun! ). Hence, using a public CDN will not automatically lead to better performance.

    Furthermore, it's worth noting that resources don't live in the browser's cache as long as we might expect, and first-party assets are more likely to stay in the cache than third-party assets. Therefore, self-hosting is usually more reliable and secure, and better for performance, too.

  2. Constrain the impact of third-party scripts.
    With all performance optimizations in place, often we can't control third-party scripts coming from business requirements. Third-party-scripts metrics aren't influenced by end-user experience, so too often one single script ends up calling a long tail of obnoxious third-party scripts, hence ruining a dedicated performance effort. To contain and mitigate performance penalties that these scripts bring along, it's not enough to just defer their loading and execution and warm up connections via resource hints, ie dns-prefetch or preconnect .

    Currently 57% of all JavaScript code excution time is spent on third-party code. The median mobile site accesses 12 third-party domains , with a median of 37 different requests (or about 3 requests made to each third party).

    Furthermore, these third-parties often invite fourth-party scripts to join in, ending up with a huge performance bottleneck, sometimes going as far as to the eigth-party scripts on a page. So regularly auditing your dependencies and tag managers can bring along costly surprises.

    Another problem, as Yoav Weiss explained in his talk on third-party scripts, is that in many cases these scripts download resources that are dynamic. The resources change between page loads, so we don't necessarily know which hosts the resources will be downloaded from and what resources they would be.

    Deferring, as shown above, might be just a start though as third-party scripts also steal bandwidth and CPU time from your app. We could be a bit more aggressive and load them only when our app has initialized.

    /* Before */ const App = () => { return <div> <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> </div> } /* After */ const App = () => { const[isRendered, setRendered] = useState(false); useEffect(() => setRendered(true)); return <div> {isRendered ? <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> : null} </div> }

    In a fantastic post on "Reducing the Site-Speed Impact of Third-Party Tags", Andy Davies explores a strategy of minimizing the footprint of third-parties — from identifying their costs towards reducing their impact.

    According to Andy, there are two ways tags impact site-speed — they compete for network bandwidth and processing time on visitors' devices, and depending on how they're implemented, they can delay HTML parsing as well. So the first step is to identify the impact that third-parties have, by testing the site with and without scripts using WebPageTest. With Simon Hearne's Request Map, we can also visualize third-parties on a page along with details on their size, type and what triggered their load.

    Preferably self-host and use a single hostname, but also use a request map to exposes fourth-party calls and detect when the scripts change. You can use Harry Roberts' approach for auditing third parties and produce spreadsheets like this one (also check Harry's auditing workflow).

    Afterwards, we can explore lightweight alternatives to existing scripts and slowly replace duplicates and main culprits with lighter options. Perhaps some of the scripts could be replaced with their fallback tracking pixel instead of the full tag.

    Left example showing 3KB of JavaScript using the lite-youtube custom element, middle and right example showing +540KB of JavaScript with the lite-youtube custom element
    Loading YouTube with facades, eg lite-youtube-embed that's significantly smaller than an actual YouTube player. (ที่มาของรูปภาพ) (ตัวอย่างขนาดใหญ่)

    If it's not viable, we can at least lazy load third-party resources with facades, ie a static element which looks similar to the actual embedded third-party, but is not functional and therefore much less taxing on the page load. The trick, then, is to load the actual embed only on interaction .

    For example, we can use:

    • lite-vimeo-embed for the Vimeo player,
    • lite-vimeo for the Vimeo player,
    • lite-youtube-embed for the YouTube player,
    • react-live-chat-loader for a live chat (case study, and another case-study),
    • lazyframe for iframes.

    One of the reasons why tag managers are usually large in size is because of the many simultaneous experiments that are running at the same time, along with many user segments, page URLs, sites etc., so according to Andy, reducing them can reduce both the download size and the time it takes to execute the script in the browser.

    And then there are anti-flicker snippets. Third-parties such as Google Optimize, Visual Web Optimizer (VWO) and others are unanimous in using them. These snippets are usually injected along with running A/B tests : to avoid flickering between the different test scenarios, they hide the body of the document with opacity: 0 , then adds a function that gets called after a few seconds to bring the opacity back. This often results in massive delays in rendering due to massive client-side execution costs.

    Seven previews shown from 0.0 seconds to 6.0 seconds showing how and when contents are hidden by the anti-flicker snippet when a visitor initiates navigation
    With A/B testing in use, customers would often see flickering like this one. Anti-Flicker snippets prevent that, but they also cost in performance. Via Andy Davies. (ตัวอย่างขนาดใหญ่)

    Therefore keep track how often the anti-flicker timeout is triggered and reduce the timeout. Default blocks display of your page by up to 4s which will ruin conversion rates. According to Tim Kadlec, "Friends don't let friends do client side A/B testing". Server-side A/B testing on CDNs (eg Edge Computing, or Edge Slice Rerendering) is always a more performant option.

    If you have to deal with almighty Google Tag Manager , Barry Pollard provides some guidelines to contain the impact of Google Tag Manager. Also, Christian Schaefer explores strategies for loading ads.

    ระวัง: วิดเจ็ตของบุคคลที่สามบางตัวซ่อนตัวจากเครื่องมือตรวจสอบ ดังนั้นจึงอาจระบุและวัดได้ยากขึ้น ในการทดสอบบุคคลที่สาม ให้ตรวจสอบสรุปจากล่างขึ้นบนในหน้าโปรไฟล์ประสิทธิภาพใน DevTools ทดสอบว่าจะเกิดอะไรขึ้นหากคำขอถูกบล็อกหรือหมดเวลา – สำหรับหลัง คุณสามารถใช้เซิร์ฟเวอร์ Blackhole ของ WebPageTest blackhole.webpagetest.org ที่คุณ สามารถชี้โดเมนเฉพาะไปที่ไฟล์ hosts ของคุณ

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

    อีกทางเลือกหนึ่งคือสร้าง นโยบายการรักษาความปลอดภัยของเนื้อหา (CSP) เพื่อจำกัดผลกระทบของสคริปต์ของบุคคลที่สาม เช่น ไม่อนุญาตให้ดาวน์โหลดเสียงหรือวิดีโอ ตัวเลือกที่ดีที่สุดคือการฝังสคริปต์ผ่าน <iframe> เพื่อให้สคริปต์ทำงานในบริบทของ iframe และด้วยเหตุนี้จึงไม่มีสิทธิ์เข้าถึง DOM ของหน้า และไม่สามารถเรียกใช้โค้ดโดยอำเภอใจบนโดเมนของคุณได้ Iframes สามารถถูกจำกัดเพิ่มเติมได้โดยใช้แอตทริบิวต์ sandbox ดังนั้นคุณสามารถปิดใช้งานฟังก์ชันการทำงานใดๆ ที่ iframe สามารถทำได้ เช่น ป้องกันไม่ให้สคริปต์ทำงาน ป้องกันการแจ้งเตือน การส่งแบบฟอร์ม ปลั๊กอิน การเข้าถึงการนำทางด้านบน และอื่นๆ

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

    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'

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

    ภาพหน้าจอของเว็บไซต์ ThirdPartyWeb.Today ที่แสดงภาพระยะเวลาที่สคริปต์ของเอนทิตีใช้ในการดำเนินการโดยเฉลี่ย
    ThirdPartyWeb.Today จัดกลุ่มสคริปต์ของบุคคลที่สามทั้งหมดตามหมวดหมู่ (การวิเคราะห์ โซเชียล โฆษณา โฮสติ้ง ตัวจัดการแท็ก ฯลฯ) และแสดงภาพว่าสคริปต์ของเอนทิตีใช้เวลาในการดำเนินการนานแค่ไหน (โดยเฉลี่ย) (ตัวอย่างขนาดใหญ่)

    พิจารณาใช้ผู้สังเกตการณ์ทางแยก ที่จะช่วยให้ โฆษณาสามารถ iframe ในขณะที่ยังคงส่งกิจกรรมหรือรับข้อมูลที่ต้องการจาก DOM (เช่น การมองเห็นโฆษณา) ระวังนโยบายใหม่ๆ เช่น นโยบายคุณลักษณะ ขีดจำกัดขนาดทรัพยากร และลำดับความสำคัญของ CPU/แบนด์วิดท์ เพื่อจำกัดคุณลักษณะเว็บที่เป็นอันตรายและสคริปต์ที่จะทำให้เบราว์เซอร์ทำงานช้าลง เช่น สคริปต์ซิงโครนัส คำขอ XHR แบบซิงโครนัส document.write และการใช้งานที่ล้าสมัย

    สุดท้าย เมื่อเลือกบริการจากภายนอก ให้พิจารณาตรวจสอบ ThirdPartyWeb ของ Patrick Hulce ในวันนี้ ซึ่งเป็นบริการที่ จัดกลุ่มสคริปต์บุคคลที่สามทั้งหมดตามหมวดหมู่ (การวิเคราะห์ โซเชียล โฆษณา โฮสติ้ง ตัวจัดการแท็ก ฯลฯ) และแสดงภาพว่าสคริปต์ของเอนทิตีนั้นใช้เวลานานเท่าใด ใช้เวลาในการดำเนินการ (โดยเฉลี่ย) เห็นได้ชัดว่าเอนทิตีที่ใหญ่ที่สุดมีผลกระทบต่อประสิทธิภาพการทำงานแย่ที่สุดกับหน้าที่พวกเขากำลังดู เพียงแค่อ่านผ่านหน้า คุณก็จะได้แนวคิดเกี่ยวกับประสิทธิภาพการทำงานที่คุณควรคาดหวัง

    อ้อ และอย่าลืมผู้ต้องสงสัยตามปกติ: แทนที่จะใช้วิดเจ็ตของบุคคลที่สามสำหรับการแบ่งปัน เราสามารถใช้ปุ่มแบ่งปันทางสังคมแบบคงที่ (เช่นโดย SSBG) และลิงก์แบบคงที่ไปยังแผนที่แบบโต้ตอบแทนแผนที่แบบโต้ตอบ

ตัวอย่างกราฟเปรียบเทียบเปอร์เซ็นต์คำขอของบุคคลที่หนึ่งและบุคคลที่สาม: 399KB จำนวน 27% ของคำขอสำหรับบุคคลที่หนึ่ง และ 1.15MB จำนวน 73% ของคำขอสำหรับบุคคลที่สาม
Casper.com เผยแพร่กรณีศึกษาโดยละเอียดเกี่ยวกับวิธีที่พวกเขาสามารถโกน 1.7 วินาทีออกจากไซต์ด้วยการโฮสต์ Optimizely ด้วยตนเอง มันอาจจะคุ้มค่า (ที่มาของรูปภาพ) (ตัวอย่างขนาดใหญ่)
  1. ตั้งค่าส่วนหัวแคช HTTP อย่างถูกต้อง
    การแคชดูเหมือนจะเป็นสิ่งที่ควรทำอย่างชัดเจน แต่อาจเป็นเรื่องยากมากที่จะให้ถูกต้อง เราจำเป็นต้องตรวจสอบอีกครั้งว่า expires , max-age , cache-control และส่วนหัวแคช HTTP อื่นๆ ได้รับการตั้งค่าอย่างถูกต้อง หากไม่มีส่วนหัวแคช HTTP ที่เหมาะสม เบราว์เซอร์จะตั้งค่าโดยอัตโนมัติที่ 10% ของเวลาที่ผ่านไปนับตั้งแต่ last-modified และจบลงด้วยการแคชที่น้อยเกินไปและอาจมีแคชมากเกินไป

    โดยทั่วไป ทรัพยากรควรแคชได้ในช่วงเวลาสั้นๆ (หากมีแนวโน้มว่าจะเปลี่ยนแปลง) หรือไม่มีกำหนด (หากเป็นแบบคงที่) คุณสามารถเปลี่ยนเวอร์ชันใน URL ได้เมื่อจำเป็น คุณสามารถเรียกมันว่ากลยุทธ์ Cache-Forever ซึ่งเราสามารถส่งต่อส่วนหัว Cache-Control และ Expires ไปยังเบราว์เซอร์เพื่ออนุญาตให้สินทรัพย์หมดอายุในหนึ่งปีเท่านั้น ดังนั้น เบราว์เซอร์จะไม่ส่งคำขอสำหรับเนื้อหาหากมีอยู่ในแคช

    ข้อยกเว้นคือการตอบสนอง API (เช่น /api/user ) เพื่อป้องกันแคช เราสามารถใช้ private, no store , และ not max-age=0, no-store :

     Cache-Control: private, no-store

    ใช้ Cache-control: immutable เพื่อหลีกเลี่ยงการตรวจสอบอายุการใช้งานแคชที่ชัดเจนอีกครั้งเมื่อผู้ใช้กดปุ่มโหลดซ้ำ สำหรับกรณีการโหลดซ้ำ แบบ immutable จะบันทึกคำขอ HTTP และปรับปรุงเวลาในการโหลดของ HTML แบบไดนามิก เนื่องจากไม่ได้แข่งขันกับการตอบกลับจำนวนมากถึง 304 รายการอีกต่อไป

    ตัวอย่างทั่วไปที่เราต้องการใช้ที่ immutable แบบคือเนื้อหา CSS/JavaScript ที่มีแฮชในชื่อ สำหรับพวกเขา เราอาจต้องการแคชให้นานที่สุด และทำให้แน่ใจว่าจะไม่ได้รับการตรวจสอบอีกครั้ง:

    Cache-Control: max-age: 31556952, immutable

    จากการวิจัยของ Colin max-age การ immutable เปลี่ยนเส้นทางช่วยลดการเปลี่ยนเส้นทาง 304 ครั้งลงได้ประมาณ 50% แม้จะใช้งานนานที่สุด ลูกค้ายังคงตรวจสอบอีกครั้งและบล็อกเมื่อรีเฟรช รองรับใน Firefox, Edge และ Safari และ Chrome ยังคงถกเถียงถึงปัญหาอยู่

    ตาม Web Almanac "การใช้งานเพิ่มขึ้นเป็น 3.5% และมีการใช้กันอย่างแพร่หลายในการตอบสนองของบุคคลที่สามของ Facebook และ Google"

    ประสิทธิภาพของการควบคุมแคชข้ามทวีปด้วยข้อมูลที่ดึงมาจาก Android Chrome และ iOS Safari
    Cache-Control: Immutable ลดลง 304s ประมาณ 50% ตามการวิจัยของ Colin Bendell ที่ Cloudinary (ตัวอย่างขนาดใหญ่)

    คุณจำเรื่องเก่าที่ดีในขณะตรวจสอบใหม่ได้หรือไม่? เมื่อเราระบุเวลาแคชด้วยส่วนหัวการตอบสนอง Cache-Control (เช่น Cache-Control: max-age=604800 ) หลังจาก max-age หมดอายุ เบราว์เซอร์จะดึงเนื้อหาที่ร้องขอใหม่ ทำให้หน้าเว็บโหลดช้าลง คุณสามารถหลีกเลี่ยงการชะลอตัวนี้ได้ด้วยการ อัปเดต stale-while-revalidate ; โดยพื้นฐานแล้วจะกำหนดกรอบเวลาพิเศษในระหว่างที่แคชสามารถใช้เนื้อหาที่ล้าสมัยได้ตราบใดที่ตรวจสอบความถูกต้องของ async ในพื้นหลังอีกครั้ง ดังนั้นจึง "ซ่อน" เวลาแฝง (ทั้งในเครือข่ายและบนเซิร์ฟเวอร์) จากไคลเอนต์

    ในเดือนมิถุนายน–กรกฎาคม 2019 Chrome และ Firefox ได้เปิดตัวการรองรับการ ไม่อัปเดต stale-while-revalidate ในส่วนหัว HTTP Cache-Control ดังนั้น จึงควรปรับปรุงเวลาแฝงในการโหลดหน้าเว็บในภายหลัง เนื่องจากเนื้อหาที่เก่าไม่อยู่ในเส้นทางวิกฤติอีกต่อไป ผลลัพธ์: RTT เป็นศูนย์สำหรับการดูซ้ำ

    ระวังส่วนหัวที่แตกต่างกัน โดยเฉพาะอย่างยิ่งในส่วนที่เกี่ยวข้องกับ CDN และระวัง HTTP Representation Variants ซึ่งช่วยหลีกเลี่ยงการเดินทางไปกลับเพิ่มเติมสำหรับการตรวจสอบเมื่อใดก็ตามที่คำขอใหม่แตกต่างเล็กน้อย (แต่ไม่สำคัญ) จากคำขอก่อนหน้า ( ขอบคุณ Guy และ Mark ! ) ).

    นอกจากนี้ ให้ตรวจสอบอีกครั้งว่าคุณไม่ได้ส่งส่วนหัวที่ไม่จำเป็น (เช่น x-powered-by , pragma , x-ua-compatible , expires , X-XSS-Protection และอื่นๆ) และคุณมีส่วนหัวด้านความปลอดภัยและประสิทธิภาพที่เป็นประโยชน์ (เช่น เช่น Content-Security-Policy , X-Content-Type-Options และอื่นๆ) สุดท้าย ให้คำนึงถึงต้นทุนประสิทธิภาพของคำขอ CORS ในแอปพลิเคชันหน้าเดียว

    หมายเหตุ : เรามักจะสันนิษฐานว่าสินทรัพย์ที่แคชถูกดึงออกมาทันที แต่การวิจัยพบว่าการดึงวัตถุจากแคชอาจใช้เวลาหลายร้อยมิลลิวินาที ตามจริงแล้ว Simon Hearne กล่าวว่า "บางครั้งเครือข่ายอาจเร็วกว่าแคช และการดึงเนื้อหาจากแคชอาจมีค่าใช้จ่ายสูงด้วยเนื้อหาแคชจำนวนมาก (ไม่ใช่ขนาดไฟล์) และอุปกรณ์ของผู้ใช้ ตัวอย่างเช่น การดึงแคชโดยเฉลี่ยของ Chrome OS เพิ่มเป็นสองเท่าจาก ~50ms พร้อมทรัพยากรแคช 5 รายการสูงถึง ~ 100ms พร้อมทรัพยากร 25 รายการ"

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

    เมื่อพูดถึงการแคช มีทรัพยากรมากมายที่ควรค่าแก่การอ่าน:

    • Cache-Control for Civilians เจาะลึกทุกสิ่งที่แคชกับ Harry Roberts
    • ไพรเมอร์ของ Heroku บนส่วนหัวแคช HTTP
    • การแคชแนวทางปฏิบัติที่ดีที่สุดโดย Jake Archibald
    • ไพรเมอร์แคช HTTP โดย Ilya Grigorik
    • รักษาความสดใหม่ด้วย Jeff Posnick ที่ค้างในขณะตรวจสอบ
    • CS Visualized: CORS โดย Lydia Hallie เป็นผู้อธิบายที่ดีเกี่ยวกับ CORS วิธีการทำงานและวิธีทำความเข้าใจ
    • เมื่อพูดถึง CORS นี่เป็นการทบทวนเล็กน้อยเกี่ยวกับนโยบายต้นกำเนิดเดียวกันโดย Eric Portis
กราฟแสดงเวลาในการดึงแคชตามจำนวนเนื้อหาที่แคชซึ่งมีชื่อระบบปฏิบัติการและเบราว์เซอร์ต่างกัน (จากบนลงล่าง): เดสก์ท็อป Chrome OS, แท็บเล็ต Android OS, ระบบปฏิบัติการ Android บนมือถือ, เดสก์ท็อป Mac =SX, เดสก์ท็อป Windows, เดสก์ท็อป Linux
เราคิดว่าแคชของเบราว์เซอร์นั้นเกือบจะทันที แต่ข้อมูลแสดงให้เห็นว่าการดึงวัตถุจากแคชอาจใช้เวลาหลายร้อยมิลลิวินาที! จากการวิจัยของ Simon Hearne เรื่อง เมื่อเครือข่ายเร็วกว่าแคช (ตัวอย่างขนาดใหญ่)

การเพิ่มประสิทธิภาพการจัดส่ง

  1. เราใช้ defer เพื่อโหลด JavaScript ที่สำคัญแบบอะซิงโครนัสหรือไม่?
    เมื่อผู้ใช้ร้องขอหน้า เบราว์เซอร์จะดึง HTML และสร้าง DOM จากนั้นดึง CSS และสร้าง CSSOM จากนั้นสร้างแผนผังการแสดงผลโดยการจับคู่ DOM และ CSSOM หากจำเป็นต้องแก้ไข JavaScript เบราว์เซอร์ จะไม่เริ่มแสดงผลหน้า จนกว่าจะได้รับการแก้ไข ซึ่งทำให้การแสดงผลล่าช้า ในฐานะนักพัฒนา เราต้องบอกเบราว์เซอร์อย่างชัดเจนว่าไม่ต้องรอและเริ่มแสดงหน้าเว็บ วิธีการทำสิ่งนี้สำหรับสคริปต์คือการใช้แอตทริบิวต์ defer และ async ใน HTML

    ในทางปฏิบัติปรากฎว่าควรใช้ defer แทน async จะดีกว่า เอ่อ ต่างกัน ยังไงหว่า? ตามที่ Steve Souders ได้กล่าวไว้ว่า เมื่อสคริปต์ async มาถึง สคริปต์เหล่านั้นจะถูกดำเนินการทันที — ทันทีที่สคริปต์พร้อม ถ้ามันเกิดขึ้นเร็วมาก เช่น เมื่อสคริปต์อยู่ในแคชแบบ aleady มันสามารถบล็อกตัวแยกวิเคราะห์ HTML ได้ ด้วย defer เบราว์เซอร์จะไม่รันสคริปต์จนกว่าจะแยกวิเคราะห์ HTML ดังนั้น เว้นแต่ว่าคุณต้องการจาวาสคริปต์เพื่อรันก่อนเริ่มการเรนเดอร์ จะดีกว่าถ้าใช้ defer นอกจากนี้ ไฟล์ async หลายไฟล์จะดำเนินการในลำดับที่ไม่ได้กำหนดไว้

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

    นอกจากนี้ ไม่แนะนำให้ใช้ทั้ง async และ defer เบราว์เซอร์สมัยใหม่รองรับทั้งสองอย่าง แต่เมื่อใดก็ตามที่มีการใช้แอตทริบิวต์ทั้งสอง async จะชนะเสมอ

    หากคุณต้องการเจาะลึกรายละเอียดเพิ่มเติม Milica Mihajlija ได้เขียนคำแนะนำโดยละเอียดเกี่ยวกับการสร้าง DOM ให้เร็วขึ้น โดยจะกล่าวถึงรายละเอียดของการแยกวิเคราะห์แบบเก็งกำไร อะซิงโครนัส และการเลื่อนเวลา

  2. ขี้เกียจโหลดส่วนประกอบราคาแพงด้วย IntersectionObserver และคำใบ้ลำดับความสำคัญ
    โดยทั่วไป ขอแนะนำให้โหลดส่วนประกอบที่มีราคาแพงทั้งหมดแบบ Lazy Loading เช่น JavaScript จำนวนมาก วิดีโอ iframe วิดเจ็ต และรูปภาพที่อาจเป็นไปได้ Native lazy-loading พร้อมใช้งานแล้วสำหรับรูปภาพและ iframes ที่มีแอตทริบิวต์การ loading (เฉพาะ Chromium) ภายใต้ประทุน คุณลักษณะนี้จะชะลอการโหลดทรัพยากรจนกว่าจะถึงระยะทางที่คำนวณได้จากวิวพอร์ต
    <!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />

    เกณฑ์นั้นขึ้นอยู่กับบางสิ่ง ตั้งแต่ประเภทของทรัพยากรรูปภาพที่ดึงข้อมูลไปจนถึงประเภทการเชื่อมต่อที่มีประสิทธิภาพ แต่การทดลองที่ดำเนินการโดยใช้ Chrome บน Android แนะนำว่าใน 4G 97.5% ของรูปภาพครึ่งหน้าล่างที่โหลดแบบ Lazy Loading ได้อย่างเต็มที่ภายใน 10 มิลลิวินาทีหลังจากที่มองเห็นได้ จึงควรปลอดภัย

    นอกจากนี้เรายังสามารถใช้แอตทริบิวต์ importance ( high หรือ low ) ในองค์ประกอบ <script> , <img> หรือ <link> (เฉพาะกะพริบเท่านั้น) อันที่จริง มันเป็นวิธีที่ยอดเยี่ยมในการลดลำดับความสำคัญของ รูปภาพ ในแบบหมุน เช่นเดียวกับการจัดลำดับความสำคัญของสคริปต์ใหม่ อย่างไรก็ตาม บางครั้งเราอาจต้องการการควบคุมที่ละเอียดกว่านี้เล็กน้อย

    <!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />

    วิธีที่มีประสิทธิภาพที่สุดในการโหลดแบบ Lazy Loading ที่ซับซ้อนกว่าเล็กน้อยคือการใช้ Intersection Observer API ที่ให้วิธีการ สังเกตการเปลี่ยนแปลงแบบอะซิงโครนัส ในส่วนตัดขององค์ประกอบเป้าหมายที่มีองค์ประกอบระดับบนสุดหรือด้วยวิวพอร์ตของเอกสารระดับบนสุด โดยพื้นฐานแล้ว คุณต้องสร้างวัตถุ IntersectionObserver ใหม่ ซึ่งรับฟังก์ชันเรียกกลับและชุดตัวเลือก จากนั้นเราเพิ่มเป้าหมายที่จะสังเกต

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

    Alejandro Garcia Anglada ได้เผยแพร่บทช่วยสอนที่มีประโยชน์เกี่ยวกับวิธีการใช้งานจริง Rahul Nanwani เขียนโพสต์โดยละเอียดเกี่ยวกับภาพพื้นหน้าและพื้นหลังที่โหลดแบบ Lazy Loading และ Google Fundamentals ให้การสอนโดยละเอียดเกี่ยวกับรูปภาพและวิดีโอที่โหลดแบบ Lazy Loading ด้วย Intersection Observer เช่นกัน

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

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

    คำเตือนสั้นๆ ที่ควรทราบ: ควรสังเกตว่าการโหลดแบบ Lazy Loading ควรเป็นข้อยกเว้นแทนที่จะเป็นกฎ อาจไม่สมเหตุสมผลที่จะโหลดสิ่งที่คุณต้องการให้คนเห็นอย่างรวดเร็วจริง ๆ เช่น รูปภาพหน้าผลิตภัณฑ์ ภาพฮีโร่ หรือสคริปต์ที่จำเป็นสำหรับการนำทางหลักเพื่อให้โต้ตอบได้

ตัวอย่างที่แสดง treshold แบบเก่าที่ 3000px พร้อมการดาวน์โหลด 160KB (ซ้าย) ในขณะที่เกณฑ์ใหม่มีจำนวน 1250px โดยมีการดาวน์โหลดเพียง 90KB (ขวา) แสดงการปรับปรุง img ในการโหลดการประหยัดข้อมูลที่ขี้เกียจ
สำหรับการเชื่อมต่อที่รวดเร็ว (เช่น 4G) ขีดจำกัดระยะห่างจากวิวพอร์ตของ Chrome ลดลงเมื่อเร็วๆ นี้จาก 3000px เป็น 1250px และในการเชื่อมต่อที่ช้ากว่า (เช่น 3G) เกณฑ์เปลี่ยนจาก 4000px เป็น 2500px (ตัวอย่างขนาดใหญ่)
ภาพประกอบพร้อมข้อความรอบ ๆ โทรศัพท์มือถือที่แสดง UI ของ Twitter อธิบายการปรับปรุงเครื่องมือจากสตริงการแปลแบบ lazy-load
ด้วยสตริงการแปลที่โหลดแบบ Lazy Loading ทำให้ Twitter บนมือถือสามารถเรียกใช้ JavaScript ได้เร็วขึ้น 80% จากไปป์ไลน์การทำให้เป็นสากลใหม่ (เครดิตรูปภาพ: Addy Osmani) (ตัวอย่างขนาดใหญ่)
  1. โหลดภาพไปเรื่อย
    คุณยังสามารถโหลดแบบ Lazy Loading ไปอีกระดับได้ด้วยการเพิ่มการโหลดภาพแบบโปรเกรสซีฟลงในหน้าเว็บของคุณ เช่นเดียวกับ Facebook, Pinterest, Medium และ Wolt คุณสามารถโหลดรูปภาพคุณภาพต่ำหรือแม้แต่ภาพเบลอก่อน จากนั้นเมื่อหน้าเว็บยังคงโหลด ให้แทนที่ด้วยเวอร์ชันคุณภาพเต็มโดยใช้เทคนิค BlurHash หรือ LQIP (ตัวยึดตำแหน่งรูปภาพคุณภาพต่ำ) เทคนิค.

    ความคิดเห็นจะต่างกันออกไปหากเทคนิคเหล่านี้ปรับปรุงประสบการณ์ผู้ใช้หรือไม่ แต่จะช่วยปรับปรุงเวลาในการใช้ First Contentful Paint ได้อย่างแน่นอน เรายังทำให้เป็นอัตโนมัติได้โดยใช้ SQIP ที่สร้างเวอร์ชันคุณภาพต่ำของรูปภาพเป็นตัวยึด SVG หรือตัวยึดตำแหน่งรูปภาพแบบไล่ระดับสีที่มีการไล่ระดับสีแบบเส้นตรง CSS

    ตัวยึดตำแหน่งเหล่านี้สามารถฝังอยู่ภายใน HTML ได้ เนื่องจากจะบีบอัดได้ดีด้วยวิธีการบีบอัดข้อความ ในบทความของเขา Dean Hume ได้อธิบายวิธีการนำเทคนิคนี้ไปใช้โดยใช้ Intersection Observer

    รั้งท้าย? หากเบราว์เซอร์ไม่รองรับการสังเกตทางแยก เราก็ยังสามารถโหลดโพลีฟิลหรือโหลดรูปภาพได้ทันที และมีแม้กระทั่งห้องสมุดสำหรับมัน

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

  2. สามเวอร์ชันที่แตกต่างกันซึ่งแสดงเทคนิคการโหลดแบบขี้เกียจ SVG โดย Jose M. Perez เวอร์ชันที่คล้ายกับงานศิลปะ Cubism ทางด้านซ้าย เวอร์ชันเบลอแบบพิกเซลตรงกลาง และรูปภาพของ Jose เองทางด้านขวา
    เทคนิคการโหลดแบบขี้เกียจ SVG โดย Jose M. Perez (ตัวอย่างขนาดใหญ่)
  3. คุณเลื่อนการแสดงผลด้วย content-visibility หรือไม่
    สำหรับเลย์เอาต์ที่ซับซ้อนซึ่งมีบล็อกเนื้อหา รูปภาพ และวิดีโอจำนวนมาก การถอดรหัสข้อมูลและพิกเซลการเรนเดอร์อาจเป็นการดำเนินการที่ค่อนข้างแพง โดยเฉพาะในอุปกรณ์ระดับล่าง ด้วย content-visibility: auto เราสามารถแจ้งให้เบราว์เซอร์ข้ามเลย์เอาต์ของเด็ก ๆ ในขณะที่คอนเทนเนอร์อยู่นอกวิวพอร์ต

    ตัวอย่างเช่น คุณอาจข้ามการแสดงผลของส่วนท้ายและส่วนท้ายในการโหลดครั้งแรก:

    footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }

    โปรดทราบว่า การมองเห็นเนื้อหา: อัตโนมัติ; ทำตัวเหมือน ล้น: ซ่อน; แต่คุณสามารถแก้ไขได้โดยการใช้ padding-left และ padding-right แทนค่า default margin-left: auto; , margin-right: auto; และความกว้างที่ประกาศไว้ ช่องว่างภายในช่วยให้องค์ประกอบล้นกล่องเนื้อหาและป้อนช่องว่างภายในโดยไม่ต้องออกจากรูปแบบกล่องโดยรวมและถูกตัดออก

    นอกจากนี้ พึงระลึกไว้เสมอว่าคุณอาจแนะนำ contain-intrinsic-size บางอย่างเมื่อเนื้อหาใหม่ได้รับการเร เดอร์ในที่สุด ดังนั้นจึงควรใช้

    Thijs Terluin มีรายละเอียดเพิ่มเติมเกี่ยวกับทั้งสองคุณสมบัติและวิธีคำนวณ contain-intrinsic-size โดยเบราว์เซอร์ Malte Ubl แสดงให้เห็นว่าคุณสามารถคำนวณได้อย่างไรและวิดีโออธิบายสั้น ๆ โดย Jake และ Surma อธิบายว่ามันทำงานอย่างไร

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

ประสิทธิภาพการเรนเดอร์ในการโหลดเริ่มต้นคือ 2,288 ms สำหรับ baseline (ซ้าย) และ 13,464 ms สำหรับส่วนที่มี content-visibility:auto (ขวา)
ในการสาธิต การใช้ content-visibility: auto ไปยังพื้นที่เนื้อหาที่เป็นกลุ่มช่วยเพิ่มประสิทธิภาพการเรนเดอร์ 7 เท่าในการโหลดครั้งแรก (ตัวอย่างขนาดใหญ่)
  1. คุณเลื่อนการถอดรหัสด้วย decoding="async" หรือไม่
    บางครั้งเนื้อหาอาจปรากฏนอกจอ แต่เราต้องการให้แน่ใจว่าจะพร้อมใช้งานเมื่อลูกค้าต้องการ — ไม่ควรปิดกั้นสิ่งใดในเส้นทางที่สำคัญ แต่เป็นการถอดรหัสและแสดงผลแบบอะซิงโครนัส เราสามารถใช้ decoding="async" เพื่อให้เบราว์เซอร์ได้รับอนุญาตให้ถอดรหัสรูปภาพจากเธรดหลัก หลีกเลี่ยงผลกระทบต่อผู้ใช้ของเวลา CPU ที่ใช้ในการถอดรหัสรูปภาพ (ผ่าน Malte Ubl):

    <img decoding="async" … />

    อีกทางหนึ่ง สำหรับรูปภาพนอกจอ เราสามารถแสดงตัวยึดตำแหน่งก่อน และเมื่อรูปภาพนั้นอยู่ภายในวิวพอร์ต โดยใช้ IntersectionObserver จะเรียกเครือข่ายให้ดาวน์โหลดรูปภาพในพื้นหลัง นอกจากนี้ เราสามารถเลื่อนการเรนเดอร์ออกไปจนกว่าจะถอดรหัสด้วย img.decode() หรือดาวน์โหลดรูปภาพหากไม่มี Image Decode API

    เมื่อทำการเรนเดอร์รูปภาพ เราสามารถใช้แอนิเมชั่นเฟดอินได้ เป็นต้น Katie Hempenius และ Addy Osmani แบ่งปันข้อมูลเชิงลึกเพิ่มเติมในการพูดคุย Speed ​​at Scale: เคล็ดลับและเทคนิคเกี่ยวกับประสิทธิภาพของเว็บจากสนามเพลาะ

  2. คุณสร้างและให้บริการ CSS ที่สำคัญหรือไม่
    เพื่อให้แน่ใจว่าเบราว์เซอร์เริ่มแสดงผลหน้าเว็บของคุณโดยเร็วที่สุด การรวบรวม CSS ทั้งหมดที่จำเป็นในการเริ่มแสดงผลส่วนแรกที่มองเห็นได้ของหน้าจึงกลายเป็นเรื่องปกติ ") และรวมไว้ใน <head> ของหน้า ซึ่งจะช่วยลดการไป-กลับ เนื่องจากขนาดแพ็กเกจที่แลกเปลี่ยนมีจำกัดในช่วงเริ่มต้นช้า งบประมาณสำหรับ CSS ที่สำคัญจึงอยู่ที่ประมาณ 14KB

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

    จากนั้นคุณสามารถอินไลน์ CSS ที่สำคัญและโหลดส่วนที่เหลือด้วยปลั๊กอิน critters Webpack หากเป็นไปได้ ให้ลองใช้วิธีการอินไลน์แบบมีเงื่อนไขที่ใช้โดย Filament Group หรือแปลงโค้ดอินไลน์เป็นสินทรัพย์แบบคงที่ได้ทันที

    หากปัจจุบันคุณ โหลด CSS แบบเต็มแบบอะซิงโครนัส กับไลบรารี เช่น loadCSS ก็ไม่จำเป็นจริงๆ ด้วย media="print" คุณสามารถหลอกให้เบราว์เซอร์ดึงข้อมูล CSS แบบอะซิงโครนัสได้ แต่จะนำไปใช้กับสภาพแวดล้อมของหน้าจอเมื่อโหลดขึ้นมา ( ขอบคุณ สกอตต์! )

    <!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />

    เมื่อรวบรวม CSS ที่สำคัญทั้งหมดสำหรับแต่ละเทมเพลต เป็นเรื่องปกติที่จะสำรวจพื้นที่ "ครึ่งหน้าบน" เพียงอย่างเดียว อย่างไรก็ตาม สำหรับเลย์เอาต์ที่ซับซ้อน อาจเป็นความคิดที่ดีที่จะรวมรากฐานของเลย์เอาต์ด้วย เพื่อ หลีกเลี่ยงการคำนวณใหม่จำนวนมาก และค่าใช้จ่ายในการทาสีใหม่ ซึ่งจะส่งผลเสียต่อคะแนน Core Web Vitals ของคุณ

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

    การใส่ CSS ที่สำคัญ (และเนื้อหาที่สำคัญอื่นๆ) ลงในไฟล์แยกต่างหากบนโดเมนรากมีประโยชน์ บางครั้งอาจมากกว่าการฝังในเนื่องจากการแคช Chrome คาดคะเนเปิดการเชื่อมต่อ HTTP ที่สองไปยังโดเมนรากเมื่อร้องขอหน้า ซึ่งไม่จำเป็นต้องใช้การเชื่อมต่อ TCP เพื่อดึงข้อมูล CSS นี้ นั่นหมายความว่าคุณสามารถสร้างชุดของ -CSS -files ที่สำคัญ (เช่น critical-homepage.css , critic-product-page.css เป็นต้น) และให้บริการจากรูทของคุณ โดยไม่ต้องอินไลน์ ( ขอบคุณฟิลิป! )

    คำเตือน: เมื่อใช้ HTTP/2 CSS ที่สำคัญสามารถจัดเก็บไว้ในไฟล์ CSS แยกต่างหาก และส่งผ่านการพุชของเซิร์ฟเวอร์โดยไม่ทำให้ HTML บวม สิ่งที่จับได้ก็คือการผลักเซิร์ฟเวอร์นั้นสร้างปัญหาให้กับ gotchas จำนวนมากและสภาวะการแข่งขันในเบราว์เซอร์ต่างๆ ไม่เคยได้รับการสนับสนุนอย่างสม่ำเสมอและมีปัญหาในการแคช (ดูสไลด์ 114 เป็นต้นไปของการนำเสนอของ Hooman Beheshti)

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

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

    นอกจากนี้ ให้หลีกเลี่ยงการวาง <link rel="stylesheet" /> ก่อนตัวอย่างข้อมูล async หากสคริปต์ไม่ได้ขึ้นอยู่กับสไตล์ชีต ให้พิจารณาวางสคริปต์การบล็อกไว้เหนือรูปแบบการบล็อก หากทำได้ ให้แบ่ง JavaScript ออกเป็นสองส่วนและโหลด CSS ไว้ที่ด้านใดด้านหนึ่ง

    Scott Jehl แก้ไขปัญหาที่น่าสนใจอีกข้อหนึ่งด้วยการแคชไฟล์ CSS แบบอินไลน์กับเจ้าหน้าที่บริการ ซึ่งเป็นปัญหาทั่วไปที่คุ้นเคยหากคุณใช้ CSS ที่สำคัญ โดยพื้นฐานแล้ว เราเพิ่มแอตทริบิวต์ ID ลงในองค์ประกอบ style เพื่อให้ง่ายต่อการค้นหาโดยใช้ JavaScript จากนั้น JavaScript ชิ้นเล็กๆ จะพบว่า CSS นั้น และใช้ Cache API เพื่อเก็บไว้ในแคชของเบราว์เซอร์ในเครื่อง (พร้อม text/css ประเภทเนื้อหา text/css ) เพื่อใช้ในหน้าถัดไป เพื่อหลีกเลี่ยงการแทรกในหน้าต่อๆ ไป และแทนที่จะอ้างอิงเนื้อหาที่แคชไว้ภายนอก เราจึงตั้งค่าคุกกี้ในการเข้าชมไซต์ครั้งแรก โว้ว!

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

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

    เราสามารถสร้างสตรีมเดียวจากหลายแหล่ง ตัวอย่างเช่น แทนที่จะให้บริการเชลล์ UI ที่ว่างเปล่าและปล่อยให้ JavaScript เติมข้อมูล คุณสามารถให้พนักงานบริการ สร้างสตรีม ที่เชลล์มาจากแคช แต่เนื้อหามาจากเครือข่าย ตามที่ Jeff Posnick ระบุไว้ หากเว็บแอปของคุณขับเคลื่อนโดย CMS ที่เซิร์ฟเวอร์แสดงผล HTML โดยการต่อเทมเพลตบางส่วนเข้าด้วยกัน โมเดลนั้นจะแปลโดยตรงเป็นการใช้การตอบสนองแบบสตรีม โดยตรรกะของเทมเพลตจะจำลองในพนักงานบริการแทนเซิร์ฟเวอร์ของคุณ บทความเรื่อง The Year of Web Streams ของ Jake Archibald เน้นย้ำว่าคุณสามารถสร้างมันขึ้นมาได้อย่างไร การเพิ่มประสิทธิภาพนั้นค่อนข้างชัดเจน

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

    รองรับเบราว์เซอร์? ยังคงไปถึงที่นั่นด้วยการสนับสนุนบางส่วนใน Chrome, Firefox, Safari และ Edge ที่รองรับ API และ Service Workers ที่ได้รับการสนับสนุนในเบราว์เซอร์ที่ทันสมัยทั้งหมด และถ้าคุณรู้สึกผจญภัยอีกครั้ง คุณสามารถตรวจสอบการใช้งานคำขอสตรีมแบบทดลอง ซึ่งช่วยให้คุณเริ่มส่งคำขอในขณะที่ยังคงสร้างเนื้อหา มีจำหน่ายใน Chrome 85

รูปภาพสรุปการใช้บันทึกข้อมูลบน Android Chrome และจำนวน img เฉลี่ยหรือเซสชันที่ค้นพบโดยการวิจัยของ Cloudinary ในเดือนพฤศจิกายน 2019 และเมษายน 2020
18% ของผู้ใช้ Android Chrome ทั่วโลกเปิดใช้งานโหมด Lite (หรือที่รู้จักว่าบันทึกข้อมูล) ตามการวิจัยของ Cloudinary (ตัวอย่างขนาดใหญ่)
  1. พิจารณาให้ส่วนประกอบของคุณทราบถึงการเชื่อมต่อ
    ข้อมูลอาจมีราคาแพงและด้วยเพย์โหลดที่เพิ่มขึ้น เราจำเป็นต้องเคารพผู้ใช้ที่เลือกใช้การประหยัดข้อมูลขณะเข้าถึงเว็บไซต์หรือแอปของเรา ส่วนหัวคำขอคำใบ้ไคลเอ็นต์บันทึกข้อมูลช่วยให้เราปรับแต่งแอปพลิเคชันและเพย์โหลดสำหรับผู้ใช้ที่จำกัดต้นทุนและประสิทธิภาพ

    ในความเป็นจริง คุณสามารถเขียนคำขอใหม่สำหรับรูปภาพ DPI สูงเป็นรูปภาพ DPI ต่ำ ลบแบบอักษรของเว็บ เอฟเฟกต์พารัลแลกซ์แฟนซี แสดงตัวอย่างขนาดย่อและการเลื่อนที่ไม่มีที่สิ้นสุด ปิดการเล่นวิดีโออัตโนมัติ เซิร์ฟเวอร์พุช ลดจำนวนรายการที่แสดงและดาวน์เกรดคุณภาพของรูปภาพ หรือ แม้กระทั่งเปลี่ยนวิธีการส่งมาร์กอัปของคุณ Tim Vereecke ได้ตีพิมพ์บทความที่มีรายละเอียดมากเกี่ยวกับกลยุทธ์ data-s(h)aver ซึ่งมีตัวเลือกมากมายสำหรับการบันทึกข้อมูล

    ใครใช้ save-data คุณอาจสงสัย? 18% ของผู้ใช้ Android Chrome ทั่วโลกเปิดใช้งานโหมด Lite (โดยเปิด Save-Data ไว้) และตัวเลขนี้มีแนวโน้มว่าจะสูงขึ้น จากการวิจัยของ Simon Hearne อัตราการเลือกใช้อุปกรณ์ที่ถูกกว่านั้นสูงที่สุด แต่ก็มีค่าผิดปกติมากมาย ตัวอย่างเช่น ผู้ใช้ในแคนาดามีอัตราการเลือกเข้าร่วมมากกว่า 34% (เทียบกับ ~7% ในสหรัฐอเมริกา) และผู้ใช้เรือธงล่าสุดของ Samsung มีอัตราการเลือกใช้เกือบ 18% ทั่วโลก

    เมื่อเปิดโหมด Save-Data Chrome Mobile จะมอบประสบการณ์ที่ปรับให้เหมาะสม เช่น ประสบการณ์เว็บที่ใช้พร็อกซีด้วยสคริปต์ที่เลื่อนออกไป font-display: swap และการโหลดแบบ Lazy Loading การสร้างประสบการณ์ด้วยตนเองเป็นเรื่องที่สมเหตุสมผลมากกว่าการพึ่งพาเบราว์เซอร์ในการเพิ่มประสิทธิภาพเหล่านี้

    ขณะนี้ส่วนหัวรองรับเฉพาะใน Chromium บน Chrome เวอร์ชัน Android หรือผ่านส่วนขยาย Data Saver บนอุปกรณ์เดสก์ท็อป สุดท้าย คุณยังสามารถใช้ Network Information API เพื่อส่งโมดูล JavaScript ที่มีราคาแพง รูปภาพและวิดีโอความละเอียดสูงตามประเภทเครือข่าย Network Information API และเฉพาะ navigator.connection.effectiveType ใช้ RTT , downlink , effectiveType ค่า (และอื่น ๆ อีกสองสามอย่าง) เพื่อนำเสนอการเชื่อมต่อและข้อมูลที่ผู้ใช้สามารถจัดการได้

    ในบริบทนี้ Max Bock พูดถึงส่วนประกอบที่รับรู้การเชื่อมต่อ และ Addy Osmani พูดถึงการให้บริการโมดูลที่ปรับเปลี่ยนได้ ตัวอย่างเช่น ด้วย React เราสามารถเขียนส่วนประกอบที่แสดงผลแตกต่างกันสำหรับประเภทการเชื่อมต่อที่แตกต่างกัน ตามที่ Max แนะนำ คอมโพเนนต์ <Media /> ในบทความข่าวอาจแสดงผล:

    • Offline : ตัว alt ตำแหน่งพร้อมข้อความแสดงแทน
    • 2G / โหมด save-data : ภาพความละเอียดต่ำ,
    • 3G บนหน้าจอที่ไม่ใช่เรตินา: ภาพความละเอียดระดับกลาง
    • 3G บนหน้าจอ Retina: ภาพ Retina ความละเอียดสูง
    • 4G : วิดีโอ HD

    Dean Hume จัดเตรียมการนำตรรกะที่คล้ายกันไปใช้ในทางปฏิบัติโดยใช้พนักงานบริการ สำหรับวิดีโอ เราสามารถแสดงโปสเตอร์วิดีโอโดยค่าเริ่มต้น จากนั้นจึงแสดงไอคอน "เล่น" รวมทั้งเปลือกโปรแกรมเล่นวิดีโอ ข้อมูลเมตาของวิดีโอ ฯลฯ ในการเชื่อมต่อที่ดีขึ้น เป็นทางเลือกสำหรับเบราว์เซอร์ที่ไม่สนับสนุน เราสามารถฟังเหตุการณ์ canplaythrough และใช้ Promise.race() เพื่อหมดเวลาการโหลดแหล่งที่มาหากเหตุการณ์ canplaythrough ไม่เริ่มทำงานภายใน 2 วินาที

    หากคุณต้องการเจาะลึกลงไปอีกเล็กน้อย ต่อไปนี้คือแหล่งข้อมูลสองสามประการเพื่อเริ่มต้น:

    • Addy Osmani แสดงวิธีการปรับใช้การให้บริการแบบปรับตัวใน React
    • React Adaptive Loading Hooks & Utilities ให้ข้อมูลโค้ดสำหรับ React
    • Netanel Basel สำรวจส่วนประกอบ Connection-Aware ในเชิงมุม
    • Theodore Vorilas แชร์วิธีการทำงานของ Adaptive Components โดยใช้ Network Information API ใน Vue
    • Umar Hansa แสดงวิธีการเลือกดาวน์โหลด/เรียกใช้ JavaScript ราคาแพง
  2. พิจารณาทำให้ส่วนประกอบของคุณรับรู้หน่วยความจำของอุปกรณ์
    การเชื่อมต่อเครือข่ายทำให้เรามีมุมมองเดียวในบริบทของผู้ใช้ ยิ่งไปกว่านั้น คุณยังสามารถปรับทรัพยากรแบบไดนามิกตามหน่วยความจำของอุปกรณ์ที่มีได้ด้วย Device Memory API navigator.deviceMemory returns how much RAM the device has in gigabytes, rounded down to the nearest power of two. The API also features a Client Hints Header, Device-Memory , that reports the same value.

    Bonus : Umar Hansa shows how to defer expensive scripts with dynamic imports to change the experience based on device memory, network connectivity and hardware concurrency.

A break-down showing how different resources are prioritized in Blink as of Chrome 46 and beyond
A break-down showing how different resources are prioritized in Blink as of Chrome 46 and beyond. (Image credit: Addy Osmani) (Large preview)
  1. Warm up the connection to speed up delivery.
    Use resource hints to save time on dns-prefetch (which performs a DNS lookup in the background), preconnect (which asks the browser to start the connection handshake (DNS, TCP, TLS) in the background), prefetch (which asks the browser to request a resource) and preload (which prefetches resources without executing them, among other things). Well supported in modern browsers, with support coming to Firefox soon.

    Remember prerender ? The resource hint used to prompt browser to build out the entire page in the background for next navigation. The implementations issues were quite problematic, ranging from a huge memory footprint and bandwidth usage to multiple registered analytics hits and ad impressions.

    Unsurprinsingly, it was deprecated, but the Chrome team has brought it back as NoState Prefetch mechanism. In fact, Chrome treats the prerender hint as a NoState Prefetch instead, so we can still use it today. As Katie Hempenius explains in that article, "like prerendering, NoState Prefetch fetches resources in advance ; but unlike prerendering, it does not execute JavaScript or render any part of the page in advance."

    NoState Prefetch only uses ~45MiB of memory and subresources that are fetched will be fetched with an IDLE Net Priority. Since Chrome 69, NoState Prefetch adds the header Purpose: Prefetch to all requests in order to make them distinguishable from normal browsing.

    Also, watch out for prerendering alternatives and portals, a new effort toward privacy-conscious prerendering, which will provide the inset preview of the content for seamless navigations.

    Using resource hints is probably the easiest way to boost performance , and it works well indeed. When to use what? As Addy Osmani has explained, it's reasonable to preload resources that we know are very likely to be used on the current page and for future navigations across multiple navigation boundaries, eg Webpack bundles needed for pages the user hasn't visited yet.

    Addy's article on "Loading Priorities in Chrome" shows how exactly Chrome interprets resource hints, so once you've decided which assets are critical for rendering, you can assign high priority to them. To see how your requests are prioritized, you can enable a "priority" column in the Chrome DevTools network request table (as well as Safari).

    Most of the time these days, we'll be using at least preconnect and dns-prefetch , and we'll be cautious with using prefetch , preload and prerender . Note that even with preconnect and dns-prefetch , the browser has a limit on the number of hosts it will look up/connect to in parallel, so it's a safe bet to order them based on priority ( thanks Philip Tellis! ).

    Since fonts usually are important assets on a page, sometimes it's a good idea to request the browser to download critical fonts with preload . However, double check if it actually helps performance as there is a puzzle of priorities when preloading fonts: as preload is seen as high importance, it can leapfrog even more critical resources like critical CSS. ( thanks, Barry! )

    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />

    Since <link rel="preload"> accepts a media attribute, you could choose to selectively download resources based on @media query rules, as shown above.

    Furthermore, we can use imagesrcset and imagesizes attributes to preload late-discovered hero images faster, or any images that are loaded via JavaScript, eg movie posters:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>

    We can also preload the JSON as fetch , so it's discovered before JavaScript gets to request it:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>

    We could also load JavaScript dynamically, effectively for lazy execution of the script.

    /* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);

    A few gotchas to keep in mind: preload is good for moving the start download time of an asset closer to the initial request, but preloaded assets land in the memory cache which is tied to the page making the request. preload plays well with the HTTP cache: a network request is never sent if the item is already there in the HTTP cache.

    Hence, it's useful for late-discovered resources, hero images loaded via background-image , inlining critical CSS (or JavaScript) and pre-loading the rest of the CSS (or JavaScript).

    An example using the cover of the Greyhound movie starring Tom Hanks to show that preloaded images load earlier as there is no need to wait on JavaScript to discover
    Preload important images early; no need to wait on JavaScript to discover them. (Image credit: “Preload Late-Discovered Hero Images Faster” by Addy Osmani) (Large preview)

    A preload tag can initiate a preload only after the browser has received the HTML from the server and the lookahead parser has found the preload tag. Preloading via the HTTP header could be a bit faster since we don't to wait for the browser to parse the HTML to start the request (it's debated though).

    Early Hints will help even further, enabling preload to kick in even before the response headers for the HTML are sent (on the roadmap in Chromium, Firefox). Plus, Priority Hints will help us indicate loading priorities for scripts.

    Beware : if you're using preload , as must be defined or nothing loads, plus preloaded fonts without the crossorigin attribute will double fetch. If you're using prefetch , beware of the Age header issues in Firefox.

A graph showing first contentful paint (by server worker status) with count from 0 to 150 across a given period of time (in ms)
With a service worker, we can request just the bare minimum of data, and then transform that data into a full HTML document to improve FCP. (via Phil Walton) (Large preview)
  1. Use service workers for caching and network fallbacks.
    No performance optimization over a network can be faster than a locally stored cache on a user's machine (there are exceptions though). If your website is running over HTTPS, we can cache static assets in a service worker cache and store offline fallbacks (or even offline pages) and retrieve them from the user's machine, rather than going to the network.

    As suggested by Phil Walton, with service workers, we can send smaller HTML payloads by programmatically generating our responses. A service worker can request just the bare minimum of data it needs from the server (eg an HTML content partial, a Markdown file, JSON data, etc.), and then it can programmatically transform that data into a full HTML document. So once a user visits a site and the service worker is installed, the user will never request a full HTML page again. The performance impact can be quite impressive.

    Browser support? Service workers are widely supported and the fallback is the network anyway. Does it help boost performance ? Oh yes, it does. And it's getting better, eg with Background Fetch allowing background uploads/downloads via a service worker as well.

    There are a number of use cases for a service worker. For example, you could implement "Save for offline" feature, handle broken images, introduce messaging between tabs or provide different caching strategies based on request types. In general, a common reliable strategy is to store the app shell in the service worker's cache along with a few critical pages, such as offline page, frontpage and anything else that might be important in your case.

    There are a few gotchas to keep in mind though. With a service worker in place, we need to beware range requests in Safari (if you are using Workbox for a service worker it has a range request module). If you ever stumbled upon DOMException: Quota exceeded. error in the browser console, then look into Gerardo's article When 7KB equals 7MB.

    ตามที่ Gerardo เขียนว่า “หากคุณกำลังสร้างเว็บแอปแบบโปรเกรสซีฟและกำลังประสบกับพื้นที่จัดเก็บแคชที่บวมเมื่อพนักงานบริการของคุณแคชสินทรัพย์แบบคงที่ที่ให้บริการจาก CDN ตรวจสอบให้แน่ใจว่าส่วนหัวการตอบสนอง CORS ที่เหมาะสมสำหรับทรัพยากรข้ามต้นทางนั้นมีอยู่ คุณจะไม่แคชการตอบกลับแบบทึบ กับพนักงานบริการของคุณโดยไม่ตั้งใจ คุณเลือกใช้เนื้อหารูปภาพข้ามต้นทางในโหมด CORS โดยเพิ่มแอตทริบิวต์ crossorigin ลงในแท็ก <img>

    มี แหล่งข้อมูลดีๆ มากมาย ในการเริ่มต้นกับพนักงานบริการ:

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

    • ข้อผิดพลาดของพนักงานบริการและแนวทางปฏิบัติที่ดีที่สุด พร้อมเคล็ดลับบางประการเกี่ยวกับขอบเขต ทำให้การลงทะเบียนพนักงานบริการและการแคชพนักงานบริการล่าช้า
    • ซีรีส์ยอดเยี่ยมโดย Ire Aderinokun เรื่อง "ออฟไลน์ก่อน" กับ Service Worker พร้อมกลยุทธ์ในการพรีแคชเปลือกแอป
    • พนักงานบริการ: บทนำพร้อมคำแนะนำที่นำไปใช้ได้จริงเกี่ยวกับวิธีการใช้พนักงานบริการเพื่อประสบการณ์ออฟไลน์ที่สมบูรณ์ การซิงค์ในเบื้องหลังเป็นระยะ และการแจ้งเตือนแบบพุช
    • การอ้างอิงถึงตำราออฟไลน์ของ Jake Archibald ที่ดีพร้อมสูตรอาหารมากมายเกี่ยวกับวิธีการอบพนักงานบริการของคุณเอง
    • Workbox คือชุดของไลบรารีพนักงานบริการที่สร้างขึ้นโดยเฉพาะสำหรับการสร้างเว็บแอปแบบโปรเกรสซีฟ
  2. คุณใช้งานเซิร์ฟเวอร์ของผู้ปฏิบัติงานบน CDN/Edge เช่น สำหรับการทดสอบ A/B หรือไม่
    ณ จุดนี้ เราค่อนข้างคุ้นเคยกับการเรียกใช้งานบริการบนไคลเอนต์ แต่ด้วยการใช้ CDN บนเซิร์ฟเวอร์ เราสามารถใช้สิ่งเหล่านี้เพื่อปรับแต่งประสิทธิภาพบนขอบได้เช่นกัน

    ตัวอย่างเช่น ในการทดสอบ A/B เมื่อ HTML จำเป็นต้องเปลี่ยนเนื้อหาสำหรับผู้ใช้ที่แตกต่างกัน เราสามารถใช้ Service Workers บนเซิร์ฟเวอร์ CDN เพื่อจัดการกับตรรกะ นอกจากนี้เรายังสามารถสตรีมการเขียน HTML ใหม่เพื่อเพิ่มความเร็วให้กับไซต์ที่ใช้ Google Fonts

กราฟแสดงอนุกรมเวลาของการติดตั้งพนักงานบริการบนเดสก์ท็อปและอุปกรณ์เคลื่อนที่พร้อมเปอร์เซ็นต์ของหน้าข้ามช่วงเวลาระหว่างเดือนมกราคม 2016 ถึงกรกฎาคม 2020
อนุกรมเวลาของการติดตั้งพนักงานบริการ เพียง 0.87% ของหน้าเดสก์ท็อปทั้งหมดที่ลงทะเบียนพนักงานบริการ ตาม Web Almanac (ตัวอย่างขนาดใหญ่)
  1. เพิ่มประสิทธิภาพการเรนเดอร์
    เมื่อใดก็ตามที่แอปพลิเคชันอืดก็สังเกตเห็นได้ทันที ดังนั้นเราจึงต้องตรวจสอบให้แน่ใจว่าไม่มีการกระตุกเมื่อเลื่อนหน้าหรือเมื่อองค์ประกอบเป็นภาพเคลื่อนไหว และคุณเข้าถึง 60 เฟรมต่อวินาทีอย่างสม่ำเสมอ หากไม่สามารถทำได้ อย่างน้อยที่สุดการทำให้เฟรมต่อวินาทีสอดคล้องกันนั้นดีกว่าสำหรับช่วงผสม 60 ถึง 15 ใช้ will-change ของ CSS เพื่อแจ้งให้เบราว์เซอร์ทราบว่าองค์ประกอบและคุณสมบัติใดที่จะเปลี่ยนแปลง

    เมื่อใดก็ตามที่คุณประสบปัญหา ให้ ดีบักการทาสีที่ไม่จำเป็น ใน DevTools:

    • วัดประสิทธิภาพการเรนเดอร์รันไทม์ ตรวจสอบคำแนะนำที่เป็นประโยชน์เกี่ยวกับวิธีการทำความเข้าใจ
    • ในการเริ่มต้น ตรวจสอบหลักสูตร Udacity ฟรีของ Paul Lewis เกี่ยวกับการเพิ่มประสิทธิภาพการแสดงผลเบราว์เซอร์และบทความของ Georgy Marchuk เกี่ยวกับการวาดภาพเบราว์เซอร์และข้อควรพิจารณาเกี่ยวกับประสิทธิภาพของเว็บ
    • เปิดใช้งาน Paint Flashing ใน "เครื่องมือเพิ่มเติม → การแสดงผล → Paint Flashing" ใน Firefox DevTools
    • ใน React DevTools ให้เลือก "ไฮไลต์การอัปเดต" และเปิดใช้งาน "บันทึกว่าทำไมแต่ละส่วนประกอบจึงแสดงผล"
    • คุณยังสามารถใช้ Why Did You Render ได้ด้วย ดังนั้นเมื่อมีการแสดงองค์ประกอบใหม่ แฟลชจะแจ้งให้คุณทราบถึงการเปลี่ยนแปลง

    คุณใช้เลย์เอาต์ของ Masonry หรือไม่? โปรดทราบว่าอาจสามารถสร้างเลย์เอาต์ Masonry ด้วยกริด CSS เพียงอย่างเดียวในเร็วๆ นี้

    หากคุณต้องการเจาะลึกในหัวข้อนี้ โนแลน ลอว์สันได้แบ่งปันกลเม็ดเพื่อวัดประสิทธิภาพของเลย์เอาต์ในบทความของเขาได้อย่างแม่นยำ และเจสัน มิลเลอร์ก็แนะนำเทคนิคทางเลือกด้วย นอกจากนี้เรายังมีบทความของ Lil' โดย Sergey Chikuyonok เกี่ยวกับวิธีทำให้ภาพเคลื่อนไหวของ GPU ถูกต้อง

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

    หมายเหตุ : การเปลี่ยนแปลงในเลเยอร์ที่ประกอบด้วย GPU นั้นมีราคาน้อยที่สุด ดังนั้นหากคุณหลีกเลี่ยงได้ด้วยการเรียกใช้การสร้างองค์ประกอบผ่าน opacity และ transform เท่านั้น คุณก็จะมาถูกทาง Anna Migas ได้ให้คำแนะนำที่เป็นประโยชน์มากมายในการพูดคุยของเธอเกี่ยวกับ Debugging UI Rendering Performance ด้วย และเพื่อให้เข้าใจวิธีการดีบักประสิทธิภาพการระบายสีใน DevTools ให้ตรวจสอบวิดีโอการตรวจสอบประสิทธิภาพของ Paint ของ Umar

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

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

    ในกรณีศึกษาของพวกเขาเกี่ยวกับ The Art of UI Skeletons Kumar McMillan จะแบ่งปันแนวคิดและเทคนิคบางอย่างเกี่ยวกับวิธีจำลองรายการแบบไดนามิก ข้อความ และหน้าจอสุดท้าย ตลอดจนวิธีพิจารณาการคิด โครงกระดูก ด้วย React

    ระวัง: หน้าจอโครงกระดูกควรได้รับการทดสอบก่อนที่จะปรับใช้ เนื่องจากการทดสอบบางอย่างแสดงให้เห็นว่าหน้าจอโครงกระดูกสามารถทำงานได้แย่ที่สุดในเมตริกทั้งหมด

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

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

    สำหรับทั้งรูปภาพหรือวิดีโอ เราสามารถใช้ตัวยึด SVG เพื่อจองกล่องแสดงผลที่สื่อจะปรากฏ ซึ่งหมายความว่าพื้นที่จะถูกจองอย่างเหมาะสมเมื่อคุณต้องรักษาอัตราส่วนกว้างยาวไว้ด้วย เรายังสามารถใช้ตัวยึดตำแหน่งหรือรูปภาพสำรองสำหรับโฆษณาและเนื้อหาแบบไดนามิก ตลอดจนการจัดสรรช่องเลย์เอาต์ล่วงหน้า

    แทนที่จะใช้อิมเมจแบบ Lazy Loading ด้วยสคริปต์ภายนอก ให้พิจารณาใช้การโหลดแบบ Lazy Loading แบบเนทีฟหรือการโหลดแบบ Lazy Loading แบบไฮบริดเมื่อเราโหลดสคริปต์ภายนอกเฉพาะเมื่อไม่รองรับการโหลดแบบ Lazy Loading ดั้งเดิม

    ดังที่กล่าวไว้ข้างต้น ให้จัดกลุ่มการทาสีฟอนต์ของเว็บใหม่และเปลี่ยนจากฟอนต์สำรอง ทั้งหมด ไปเป็นฟอนต์ของเว็บ ทั้งหมด ในคราวเดียว — เพียงตรวจสอบให้แน่ใจว่าสวิตช์นั้นไม่กะทันหันเกินไป โดยการปรับความสูงของบรรทัดและระยะห่างระหว่างฟอนต์ด้วย font-style-matcher .

    หากต้องการ ลบล้างเมตริกแบบอักษร สำหรับแบบอักษรสำรองเพื่อจำลองแบบอักษรของเว็บ เราสามารถใช้ @font-face descriptors เพื่อแทนที่เมตริกแบบอักษร (สาธิต เปิดใช้งานใน Chrome 87) (โปรดทราบว่าการปรับเปลี่ยนนั้นซับซ้อนด้วยกองฟอนต์ที่ซับซ้อนแม้ว่า)

    สำหรับ CSS ตอนปลาย เราสามารถมั่นใจได้ว่า CSS ที่มีความสำคัญต่อการจัดวางอยู่ ในส่วนหัวของแต่ละเทมเพลต ยิ่งไปกว่านั้น สำหรับหน้าที่ยาว เมื่อเพิ่มแถบเลื่อนแนวตั้ง จะเลื่อนเนื้อหาหลักไปทางซ้ายเป็น 16px ในการแสดงแถบเลื่อนในช่วงต้น เราสามารถเพิ่ม overflow-y: scroll บน html เพื่อบังคับใช้แถบเลื่อนในครั้งแรกที่ระบายสี อย่างหลังช่วยได้เพราะแถบเลื่อนอาจทำให้เกิดการเลื่อนเลย์เอาต์ที่ไม่สำคัญเนื่องจากเนื้อหาครึ่งหน้าบนจะรีโฟลว์เมื่อความกว้างเปลี่ยนแปลง ส่วนใหญ่ควรเกิดขึ้นบนแพลตฟอร์มที่มีแถบเลื่อนที่ไม่ใช่โอเวอร์เลย์เช่น Windows แต่: แตก position: sticky เพราะองค์ประกอบเหล่านั้นจะไม่มีวันเลื่อนออกจากคอนเทนเนอร์

    หากคุณจัดการกับส่วนหัวที่คงที่หรือติดหนึบอยู่ที่ด้านบนของหน้าเมื่อเลื่อน ให้จองพื้นที่สำหรับส่วนหัวเมื่อกลายเป็นไพน์ เช่น ตัวยึดตำแหน่งหรือ margin-top ของเนื้อหา ข้อยกเว้นควรเป็นแบนเนอร์ขอความยินยอมในการใช้คุกกี้ที่ไม่มีผลกระทบต่อ CLS แต่บางครั้งก็มี: ขึ้นอยู่กับการใช้งาน มีกลยุทธ์และประเด็นที่น่าสนใจสองสามข้อในหัวข้อ Twitter นี้

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

    อ้อ และแน่นอน การเลื่อนแบบไม่สิ้นสุดและ "โหลดเพิ่ม" อาจทำให้เลย์เอาต์เปลี่ยนได้เช่นกัน หากมีเนื้อหาด้านล่างรายการ (เช่น ส่วนท้าย) เพื่อปรับปรุง CLS ให้จองพื้นที่เพียงพอสำหรับเนื้อหาที่จะโหลด ก่อน ที่ผู้ใช้จะเลื่อนไปยังส่วนนั้นของหน้า ลบส่วนท้ายหรือองค์ประกอบ DOM ใด ๆ ที่ด้านล่างของหน้าที่อาจผลักลงโดยการโหลดเนื้อหา นอกจากนี้ ดึงข้อมูลและรูปภาพล่วงหน้าสำหรับเนื้อหาครึ่งหน้าล่าง เพื่อที่เมื่อผู้ใช้เลื่อนไปไกลถึงขนาดนั้น ก็อยู่ที่นั่นแล้ว คุณสามารถใช้ list virtualization library เช่น react-window เพื่อเพิ่มประสิทธิภาพรายการแบบยาวได้เช่นกัน ( ขอบคุณ Addy Osmani! )

    เพื่อให้แน่ใจว่าผลกระทบของการรีโฟลว์มีอยู่ ให้วัดความเสถียรของเลย์เอาต์ด้วย Layout Instability API ด้วยเครื่องมือนี้ คุณสามารถคำนวณคะแนน Cumulative Layout Shift ( CLS ) และรวมไว้เป็นข้อกำหนดในการทดสอบของคุณ ดังนั้นเมื่อใดก็ตามที่การถดถอยปรากฏขึ้น คุณสามารถติดตามและแก้ไขได้

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

    เคล็ดลับด่วน : หากต้องการค้นหาสาเหตุที่ทำให้เกิดการเปลี่ยนเลย์เอาต์ใน DevTools คุณสามารถสำรวจการเปลี่ยนเลย์เอาต์ภายใต้ "ประสบการณ์" ในแผงประสิทธิภาพ

    โบนัส : หากคุณต้องการลด reflows และ repaints ให้ดูที่ Charis Theodoulou's guide to Minimizing DOM Reflow/Layout Thrashing และ Paul Irish's ของ What Force Layout / reflow รวมถึง CSSTriggers.com ตารางอ้างอิงเกี่ยวกับคุณสมบัติ CSS ที่เรียกเลย์เอาต์, ระบายสี และการเรียบเรียง

เครือข่ายและ HTTP/2

  1. มีการเปิดใช้การเย็บเล่ม OCSP หรือไม่
    การเปิดใช้งานการเย็บเล่ม OCSP บนเซิร์ฟเวอร์ของคุณ จะทำให้การจับมือ TLS ของคุณเร็วขึ้น โปรโตคอลสถานะใบรับรองออนไลน์ (OCSP) ถูกสร้างขึ้นเป็นทางเลือกแทนโปรโตคอลรายการเพิกถอนใบรับรอง (CRL) โปรโตคอลทั้งสองถูกใช้เพื่อตรวจสอบว่าใบรับรอง SSL ถูกเพิกถอนหรือไม่

    อย่างไรก็ตาม โปรโตคอล OCSP ไม่ต้องการให้เบราว์เซอร์ใช้เวลาในการดาวน์โหลดแล้วค้นหารายการข้อมูลใบรับรอง ดังนั้นจึงช่วยลดเวลาที่ต้องใช้สำหรับการจับมือกัน

  2. คุณได้ลดผลกระทบจากการเพิกถอนใบรับรอง SSL หรือไม่
    ในบทความของเขาเรื่อง "The Performance Cost of EV Certificates" Simon Hearne ให้ภาพรวมที่ดีของใบรับรองทั่วไป และผลกระทบที่การเลือกใบรับรองอาจมีต่อประสิทธิภาพโดยรวม

    ตามที่ Simon เขียน ในโลกของ HTTPS มีระดับการตรวจสอบใบรับรองบางประเภทที่ใช้เพื่อความปลอดภัยของการรับส่งข้อมูล:

    • การตรวจสอบความถูกต้องของ โดเมน (DV) ตรวจสอบว่าผู้ขอใบรับรองเป็นเจ้าของโดเมน
    • การ ตรวจสอบองค์กร (OV) ตรวจสอบว่าองค์กรเป็นเจ้าของโดเมน
    • Extended Validation (EV) ตรวจสอบว่าองค์กรเป็นเจ้าของโดเมนด้วยการตรวจสอบอย่างเข้มงวด

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

    ใบรับรอง EV มีราคาแพงและใช้เวลานาน เนื่องจากต้องมีเจ้าหน้าที่ตรวจสอบใบรับรองและรับรองความถูกต้อง ในทางกลับกัน ใบรับรอง DV มักจะให้บริการฟรี — เช่น โดย Let's Encrypt — ผู้ออกใบรับรองอัตโนมัติแบบเปิดที่รวมเข้ากับผู้ให้บริการโฮสต์และ CDN จำนวนมาก ในความเป็นจริง ในขณะที่เขียน มันมีอำนาจมากกว่า 225 ล้านเว็บไซต์ (PDF) แม้ว่าจะทำได้เพียง 2.69% ของหน้า (เปิดใน Firefox)

    แล้วมีปัญหาอะไรไหม? ปัญหาคือ ใบรับรอง EV ไม่รองรับการเย็บเล่ม OCSP ที่กล่าวถึงข้างต้นอย่างสมบูรณ์ ในขณะที่การเย็บเล่มช่วยให้เซิร์ฟเวอร์ตรวจสอบกับผู้ออกใบรับรองว่าใบรับรองถูกเพิกถอนหรือไม่ จากนั้นจึงเพิ่ม ("เย็บเล่ม") ข้อมูลนี้ในใบรับรอง โดยไม่ต้องเย็บเล่ม ไคลเอ็นต์ต้องทำงานทั้งหมด ส่งผลให้มีคำขอที่ไม่จำเป็นในระหว่างการเจรจา TLS . สำหรับการเชื่อมต่อที่ไม่ดี อาจมีค่าใช้จ่ายด้านประสิทธิภาพที่เห็นได้ชัดเจน (1000ms+)

    ใบรับรอง EV ไม่ใช่ตัวเลือกที่ดีสำหรับประสิทธิภาพของเว็บ และสามารถสร้างผลกระทบต่อประสิทธิภาพที่ใหญ่กว่าใบรับรอง DV ได้ เพื่อประสิทธิภาพเว็บที่ดีที่สุด ให้ใช้ใบรับรอง DV แบบเย็บเล่ม OCSP เสมอ พวกเขายังถูกกว่าใบรับรอง EV มากและยุ่งยากน้อยกว่าที่จะได้รับ อย่างน้อยก็จนกว่า CRLite จะพร้อมใช้งาน

    กราฟแสดงจำนวนการจับมือกับดาตาแกรม UDP ในกรณีธรรมดา บีบอัด หรือทั้งสองอย่าง
    การบีบอัดมีความสำคัญ: 40–43% ของสายใบรับรองที่ไม่ได้บีบอัดนั้นใหญ่เกินกว่าจะใส่ลงในเที่ยวบิน QUIC เดียวของ 3 UDP ดาตาแกรม (เครดิตรูปภาพ:) อย่างรวดเร็ว) (ตัวอย่างขนาดใหญ่)

    หมายเหตุ : เมื่อใช้ QUIC/HTTP/3 กับเรา เราควรสังเกตว่าห่วงโซ่ใบรับรอง TLS เป็นเนื้อหาขนาดตัวแปรเดียวที่ควบคุมจำนวนไบต์ใน QUIC Handshake ขนาดแตกต่างกันระหว่างสองสามร้อยบายและมากกว่า 10 KB

    ดังนั้น การรักษาใบรับรอง TLS นั้นเป็นเรื่องเล็กน้อยบน QUIC/HTTP/3 อย่างมาก เนื่องจากใบรับรองขนาดใหญ่จะทำให้เกิดการจับมือกันหลายครั้ง นอกจากนี้ เราต้องตรวจสอบให้แน่ใจว่าใบรับรองถูกบีบอัด มิฉะนั้น ห่วงโซ่ใบรับรองจะใหญ่เกินกว่าจะใส่ลงในเที่ยวบิน QUIC เดียวได้

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

    • ใบรับรอง EV ทำให้เว็บช้าและไม่น่าเชื่อถือ โดย Aaron Peters
    • ผลกระทบของการเพิกถอนใบรับรอง SSL ต่อประสิทธิภาพของเว็บโดย Matt Hobbs
    • ต้นทุนประสิทธิภาพของใบรับรอง EV โดย Simon Hearne
    • การจับมือ QUIC ต้องการการบีบอัดให้เร็วหรือไม่? โดย แพทริก แมคมานัส
  3. คุณได้ใช้ IPv6 แล้วหรือยัง?
    เนื่องจากพื้นที่ IPv4 ของเราใกล้จะหมดลงแล้ว และเครือข่ายมือถือหลักๆ ก็เริ่มนำ IPv6 มาใช้อย่างรวดเร็ว (ในสหรัฐฯ เกือบจะถึงเกณฑ์การยอมรับ IPv6 ถึง 50% แล้ว) จึงเป็นความคิดที่ดีที่จะอัปเดต DNS ของคุณเป็น IPv6 เพื่อให้สามารถกันกระสุนได้ในอนาคต เพียงตรวจสอบให้แน่ใจว่ามีการรองรับ dual-stack ทั่วทั้งเครือข่าย — ทำให้ IPv6 และ IPv4 ทำงานพร้อมกันพร้อมกันได้ ท้ายที่สุดแล้ว IPv6 นั้นไม่สามารถเข้ากันได้แบบย้อนหลัง นอกจากนี้ จากการศึกษาพบว่า IPv6 ทำให้เว็บไซต์เหล่านั้นเร็วขึ้น 10 ถึง 15% เนื่องจากการค้นพบเพื่อนบ้าน (NDP) และการเพิ่มประสิทธิภาพเส้นทาง
  4. ตรวจสอบให้แน่ใจว่าเนื้อหาทั้งหมดทำงานผ่าน HTTP/2 (หรือ HTTP/3)
    ด้วยการที่ Google มุ่งสู่เว็บ HTTPS ที่ปลอดภัยยิ่งขึ้นในช่วงไม่กี่ปีที่ผ่านมา การเปลี่ยนไปใช้สภาพแวดล้อม HTTP/2 ถือเป็นการลงทุนที่ดีอย่างแน่นอน จากข้อมูลของ Web Almanac พบว่า 64% ของคำขอทั้งหมดทำงานผ่าน HTTP/2 แล้ว

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

    คำเตือน: กำลังนำ HTTP/2 Server Push ออกจาก Chrome ดังนั้นหากการใช้งานของคุณต้องอาศัย Server Push คุณอาจต้องกลับมาตรวจสอบอีกครั้ง แต่เราอาจกำลังดู Early Hints ซึ่งรวมเข้ากับการทดลองใน Fastly อยู่แล้ว

    หากคุณยังคงทำงานบน HTTP งานที่ต้องใช้เวลามากที่สุดคือการโยกย้ายไปยัง HTTPS ก่อน แล้วจึงปรับกระบวนการสร้างของคุณเพื่อรองรับ HTTP/2 มัลติเพล็กซ์และการทำให้ขนานกัน การนำ HTTP/2 มาสู่ Gov.uk เป็นกรณีศึกษาที่ยอดเยี่ยมในการทำเช่นนั้น โดยค้นหาวิธีผ่าน CORS, SRI และ WPT ไปพร้อมกัน สำหรับส่วนที่เหลือของบทความนี้ เราคิดว่าคุณกำลังเปลี่ยนไปใช้ HTTP/2 แล้ว

กราฟแสดงอนุกรมเวลาของคำขอ HTTP/2 ทั้งบนเดสก์ท็อปและอุปกรณ์เคลื่อนที่ ตั้งแต่วันที่ 2 มกราคม 2016 ถึง 1 ตุลาคม 2020
64% ของคำขอทั้งหมดให้บริการผ่าน HTTP/2 ในปลายปี 2020 ตามรายงานของ Web Almanac — เพียง 4 ปีหลังจากการกำหนดมาตรฐานอย่างเป็นทางการ (ที่มาของรูปภาพ: Web Almanac) (ตัวอย่างขนาดใหญ่)
  1. ปรับใช้ HTTP/2 อย่างเหมาะสม
    อีกครั้ง การแสดงเนื้อหาผ่าน HTTP/2 จะได้รับประโยชน์จากการยกเครื่องบางส่วนของวิธีการให้บริการเนื้อหาของคุณจนถึงตอนนี้ คุณจะต้องหาจุดสมดุลที่ดีระหว่างโมดูลการบรรจุและการโหลดโมดูลขนาดเล็กจำนวนมากพร้อมกัน ในตอนท้าย คำขอที่ดีที่สุดยังคงไม่ใช่คำขอ อย่างไรก็ตาม เป้าหมายคือการหาสมดุลที่ดีระหว่างการส่งมอบสินทรัพย์ครั้งแรกอย่างรวดเร็วและการแคช

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

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

    โค้ด HTML โดยใช้การโหลด CSS แบบโปรเกรสซีฟ
    เพื่อให้ได้ผลลัพธ์ที่ดีที่สุดกับ HTTP/2 ให้พิจารณาโหลด CSS แบบค่อยเป็นค่อยไป ตามที่ Jake Archibald ของ Chrome แนะนำ

    อย่างไรก็ตาม คุณสามารถลองโหลด CSS แบบค่อยเป็นค่อยไป อันที่จริงแล้ว CSS ในเนื้อหาจะไม่บล็อกการเรนเดอร์สำหรับ Chrome อีกต่อไป แต่มีปัญหาการจัดลำดับความสำคัญบางอย่าง จึงไม่ตรงไปตรงมา แต่ควรค่าแก่การทดลองด้วย

    คุณสามารถหลีกหนีจากการรวมการเชื่อมต่อ HTTP/2 ได้ ซึ่งทำให้คุณสามารถใช้การแบ่งส่วนโดเมนในขณะที่ใช้ประโยชน์จาก HTTP/2 ได้ แต่การบรรลุสิ่งนี้ในทางปฏิบัตินั้นยาก และโดยทั่วไปแล้ว ไม่ถือเป็นแนวปฏิบัติที่ดี นอกจากนี้ HTTP/2 และ Subresource Integrity ไม่ได้เปิดใช้งานเสมอไป

    จะทำอย่างไร? หากคุณใช้งานผ่าน HTTP/2 การส่ง แพ็คเกจประมาณ 6–10 รายการดูเหมือนจะเป็นการประนีประนอมที่ดี (และไม่เลวร้ายเกินไปสำหรับเบราว์เซอร์รุ่นเก่า) ทดลองและวัดผลเพื่อหาจุดสมดุลที่เหมาะสมสำหรับเว็บไซต์ของคุณ

  2. เราส่งทรัพย์สินทั้งหมดผ่านการเชื่อมต่อ HTTP/2 เดียวหรือไม่
    ข้อดีหลักประการหนึ่งของ HTTP/2 คือช่วยให้เราส่งทรัพย์สินผ่านสายผ่านการเชื่อมต่อเพียงครั้งเดียว อย่างไรก็ตาม บางครั้งเราอาจทำอะไรผิดพลาดไป เช่น มีปัญหา CORS หรือกำหนดค่าแอตทริบิวต์ crossorigin ผิด ดังนั้นเบราว์เซอร์จะถูกบังคับให้เปิดการเชื่อมต่อใหม่

    หากต้องการตรวจสอบว่าคำขอทั้งหมดใช้การเชื่อมต่อ HTTP/2 เดียวหรือมีการกำหนดค่าบางอย่างผิดพลาด ให้เปิดใช้งานคอลัมน์ "ID การเชื่อมต่อ" ใน DevTools → Network เช่น ที่นี่ คำขอทั้งหมดมีการเชื่อมต่อเดียวกัน (286) — ยกเว้น manifest.json ซึ่งเปิดแยกต่างหาก (451)

สกรีนช็อตของ DevTools ที่เปิดอยู่ในเบราว์เซอร์ Chrome
คำขอทั้งหมดใช้การเชื่อมต่อ HTTP/2 เดียวกัน (286) — ยกเว้น manifest.json ซึ่งเปิดแยกต่างหาก (451) โดย iamakulov (ตัวอย่างขนาดใหญ่)
  1. เซิร์ฟเวอร์และ CDN ของคุณรองรับ HTTP/2 หรือไม่
    เซิร์ฟเวอร์และ CDN (ยังคง) ต่างกันรองรับ HTTP/2 ต่างกัน ใช้การเปรียบเทียบ CDN เพื่อตรวจสอบตัวเลือกของคุณ หรือค้นหาอย่างรวดเร็วว่าเซิร์ฟเวอร์ของคุณทำงานเป็นอย่างไร และคุณลักษณะใดที่คุณคาดว่าจะได้รับการสนับสนุน

    ปรึกษางานวิจัยที่น่าทึ่งของ Pat Meenan เกี่ยวกับลำดับความสำคัญของ HTTP/2 (วิดีโอ) และทดสอบการสนับสนุนเซิร์ฟเวอร์สำหรับการจัดลำดับความสำคัญ HTTP/2 ตาม Pat ขอแนะนำให้เปิดใช้งานการควบคุมความแออัดของ BBR และตั้งค่า tcp_notsent_lowat เป็น 16KB สำหรับการจัดลำดับความสำคัญ HTTP/2 เพื่อให้ทำงานได้อย่างน่าเชื่อถือบนเคอร์เนล Linux 4.9 และใหม่กว่า ( ขอบคุณ Yoav! ) Andy Davies ได้ทำการวิจัยที่คล้ายกันสำหรับการจัดลำดับความสำคัญของ HTTP/2 ในเบราว์เซอร์, CDN และ Cloud Hosting Services

    ในขณะนั้น ให้ตรวจสอบอีกครั้งว่าเคอร์เนลของคุณรองรับ TCP BBR หรือไม่ และเปิดใช้งานหากเป็นไปได้ ปัจจุบันใช้บน Google Cloud Platform, Amazon Cloudfront, Linux (เช่น Ubuntu)

  2. มีการใช้การบีบอัด HPACK หรือไม่
    หากคุณกำลังใช้ HTTP/2 ให้ตรวจสอบอีกครั้งว่าเซิร์ฟเวอร์ของคุณใช้การบีบอัด HPACK สำหรับส่วนหัวการตอบสนอง HTTP เพื่อลดโอเวอร์เฮดที่ไม่จำเป็น เซิร์ฟเวอร์ HTTP/2 บางเครื่องอาจไม่รองรับข้อกำหนดนี้โดยสมบูรณ์ โดยมี HPACK เป็นตัวอย่าง H2spec เป็นเครื่องมือที่ยอดเยี่ยม (หากมีรายละเอียดทางเทคนิคมาก) ในการตรวจสอบ อัลกอริธึมการบีบอัดของ HPACK นั้นค่อนข้างน่าประทับใจและได้ผล
  3. ตรวจสอบให้แน่ใจว่าการรักษาความปลอดภัยบนเซิร์ฟเวอร์ของคุณเป็นแบบกันกระสุน
    การใช้งานเบราว์เซอร์ทั้งหมดของ HTTP/2 ทำงานบน TLS ดังนั้นคุณอาจต้องการหลีกเลี่ยงคำเตือนด้านความปลอดภัยหรือองค์ประกอบบางอย่างในหน้าเว็บของคุณไม่ทำงาน ตรวจสอบอีกครั้งว่าส่วนหัวความปลอดภัยของคุณได้รับการตั้งค่าอย่างถูกต้อง กำจัดช่องโหว่ที่ทราบ และตรวจสอบการตั้งค่า HTTPS ของคุณ

    นอกจากนี้ ตรวจสอบให้แน่ใจว่าปลั๊กอินภายนอกและสคริปต์ติดตามทั้งหมดโหลดผ่าน HTTPS สคริปต์ข้ามไซต์นั้นเป็นไปไม่ได้ และทั้งส่วนหัว HTTP Strict Transport Security และส่วนหัวของนโยบายความปลอดภัยเนื้อหาได้รับการตั้งค่าอย่างเหมาะสม

  4. เซิร์ฟเวอร์และ CDN ของคุณรองรับ HTTP/3 หรือไม่
    ในขณะที่ HTTP/2 ได้นำการปรับปรุงประสิทธิภาพที่สำคัญหลายประการมาสู่เว็บ แต่ก็ยังเหลือพื้นที่สำหรับการปรับปรุงอยู่บ้าง โดยเฉพาะอย่างยิ่งการบล็อกส่วนหัวของบรรทัดใน TCP ซึ่งสังเกตเห็นได้ชัดเจนในเครือข่ายที่ช้าและมีแพ็กเก็ตสูญหายอย่างมีนัยสำคัญ HTTP/3 กำลังแก้ไขปัญหาเหล่านี้ให้ดี (บทความ)

    เพื่อแก้ไขปัญหา HTTP/2 IETF พร้อมด้วย Google, Akamai และอื่นๆ ได้ทำงานบนโปรโตคอลใหม่ที่เพิ่งได้รับมาตรฐานเป็น HTTP/3

    Robin Marx อธิบาย HTTP/3 ได้ดีมาก และคำอธิบายต่อไปนี้ก็มาจากคำอธิบายของเขา โดยพื้นฐานแล้ว HTTP/3 นั้นคล้ายกับ HTTP/2 มาก ในแง่ของคุณสมบัติ แต่ภายใต้ประทุนนั้นทำงานแตกต่างกันมาก HTTP/3 มีการปรับปรุงหลายอย่าง: การจับมือที่เร็วขึ้น การเข้ารหัสที่ดีขึ้น สตรีมอิสระที่เชื่อถือได้มากขึ้น การเข้ารหัสที่ดีขึ้น และการควบคุมการไหล ความแตกต่างที่น่าสังเกตคือ HTTP/3 ใช้ QUIC เป็นเลเยอร์การขนส่ง โดยมีแพ็กเก็ต QUIC ห่อหุ้มที่ด้านบนของไดอะแกรม UDP แทนที่จะเป็น TCP

    QUIC ผสานรวม TLS 1.3 เข้ากับโปรโตคอลอย่างสมบูรณ์ ในขณะที่ TCP จะอยู่ด้านบนสุด ในสแต็ก TCP ทั่วไป เรามีโอเวอร์เฮดไปกลับสองสามครั้งเนื่องจาก TCP และ TLS จำเป็นต้องทำแฮนด์เชคแยกกัน แต่ด้วย QUIC ทั้งคู่สามารถ รวมและแล้วเสร็จได้ในการไปกลับเพียงครั้งเดียว เนื่องจาก TLS 1.3 ช่วยให้เราตั้งค่าคีย์การเข้ารหัสสำหรับการเชื่อมต่อที่ตามมาได้ ตั้งแต่การเชื่อมต่อครั้งที่สองเป็นต้นไป เราจึงสามารถส่งและรับข้อมูลเลเยอร์แอปพลิเคชันในการไปกลับครั้งแรกซึ่งเรียกว่า "0-RTT"

    นอกจากนี้ อัลกอริธึมการบีบอัดส่วนหัวของ HTTP/2 ยังถูกเขียนใหม่ทั้งหมด พร้อมด้วยระบบการจัดลำดับความสำคัญ นอกจากนี้ QUIC ยังรองรับ การย้ายการเชื่อมต่อ จาก Wi-Fi ไปยังเครือข่ายเซลลูลาร์ผ่าน ID การเชื่อมต่อในส่วนหัวของแพ็กเก็ต QUIC แต่ละแพ็กเก็ตอีกด้วย การใช้งานส่วนใหญ่เสร็จสิ้นในพื้นที่ผู้ใช้ ไม่ใช่พื้นที่เคอร์เนล (เหมือนที่ทำกับ TCP) ดังนั้นเราควรคาดหวังว่าโปรโตคอลจะมีการพัฒนาในอนาคต

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

    ซึ่งหมายความว่าในขณะที่กลุ่ม JavaScript ขนาดใหญ่กลุ่มเดียว การประมวลผลเนื้อหาจะช้าลงเมื่อสตรีมหนึ่งหยุดชั่วคราว ผลกระทบจะมีนัยสำคัญน้อยลงเมื่อไฟล์หลายไฟล์สตรีมพร้อมกัน (HTTP/3) ดังนั้น บรรจุภัณฑ์จึงยังคงมีความสำคัญ

    HTTP/3 ยังคงทำงานอยู่ Chrome, Firefox และ Safari มีการใช้งานอยู่แล้ว CDN บางตัวรองรับ QUIC และ HTTP/3 แล้ว ในช่วงปลายปี 2020 Chrome ได้เริ่มปรับใช้ HTTP/3 และ IETF QUIC และที่จริงแล้วบริการของ Google ทั้งหมด (Google Analytics, YouTube ฯลฯ) นั้นทำงานบน HTTP/3 อยู่แล้ว LiteSpeed ​​Web Server รองรับ HTTP/3 แต่ Apache, nginx หรือ IIS ยังไม่รองรับ แต่มีแนวโน้มที่จะเปลี่ยนแปลงอย่างรวดเร็วในปี 2021

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

    หากคุณต้องการเจาะลึกข้อมูลเฉพาะและข้อดีของโปรโตคอล ต่อไปนี้คือจุดเริ่มต้นที่ดีที่ควรตรวจสอบ:

    • HTTP/3 อธิบายเป็นความพยายามร่วมกันในการจัดทำเอกสารโปรโตคอล HTTP/3 และ QUIC มีให้บริการในภาษาต่างๆ รวมทั้งในรูปแบบ PDF
    • ยกระดับประสิทธิภาพของเว็บด้วย HTTP/3 ด้วย Daniel Stenberg
    • คำแนะนำทางวิชาการของ QUIC กับ Robin Marx นำเสนอแนวคิดพื้นฐานของโปรโตคอล QUIC และ HTTP/3 อธิบายว่า HTTP/3 จัดการกับการบล็อกส่วนหัวและการย้ายการเชื่อมต่ออย่างไร และ HTTP/3 ได้รับการออกแบบอย่างไรให้คงอยู่ตลอดไป (ขอบคุณ Simon !).
    • คุณสามารถตรวจสอบว่าเซิร์ฟเวอร์ของคุณทำงานบน HTTP/3 บน HTTP3Check.net หรือไม่

การทดสอบและการตรวจสอบ

  1. คุณได้ปรับเวิร์กโฟลว์การตรวจสอบของคุณให้เหมาะสมแล้วหรือยัง?
    อาจฟังดูไม่ใช่เรื่องใหญ่ แต่การมีการตั้งค่าที่เหมาะสมไว้เพียงปลายนิ้วสัมผัสอาจช่วยคุณประหยัดเวลาในการทดสอบได้ไม่น้อย ลองใช้ Alfred Workflow ของ Tim Kadlec สำหรับ WebPageTest เพื่อส่งการทดสอบไปยังอินสแตนซ์สาธารณะของ WebPageTest อันที่จริง WebPageTest มีคุณลักษณะที่ไม่ชัดเจนมากมาย ดังนั้นโปรดใช้เวลาเรียนรู้วิธีอ่านแผนภูมิ WebPageTest Waterfall View และวิธีอ่านแผนภูมิ WebPageTest Connection View เพื่อวินิจฉัยและแก้ไขปัญหาด้านประสิทธิภาพได้เร็วขึ้น

    คุณยังสามารถขับเคลื่อน WebPageTest จาก Google Spreadsheet และรวมคะแนนการช่วยสำหรับการเข้าถึง ประสิทธิภาพ และ SEO เข้าในการตั้งค่า Travis ของคุณด้วย Lighthouse CI หรือโดยตรงใน Webpack

    ดู AutoWebPerf ที่เพิ่งเปิดตัว ซึ่งเป็นเครื่องมือโมดูลาร์ที่ช่วยให้สามารถรวบรวมข้อมูลประสิทธิภาพจากแหล่งที่มาต่างๆ ได้โดยอัตโนมัติ ตัวอย่างเช่น เราสามารถตั้งค่าการทดสอบรายวันบนหน้าที่สำคัญของคุณเพื่อเก็บข้อมูลภาคสนามจาก CrUX API และข้อมูลห้องทดลองจากรายงาน Lighthouse จาก PageSpeed ​​Insights

    และถ้าคุณต้องการแก้จุดบกพร่องอย่างรวดเร็ว แต่กระบวนการสร้างของคุณดูเหมือนจะช้ามาก โปรดจำไว้ว่า "การลบช่องว่างและการจัดการสัญลักษณ์คิดเป็น 95% ของการลดขนาดในโค้ดย่อขนาดสำหรับ JavaScript ส่วนใหญ่ — ไม่ใช่การแปลงโค้ดที่ซับซ้อน คุณสามารถ เพียงปิดการใช้งานการบีบอัดเพื่อเพิ่มความเร็วให้กับ Uglify บิลด์ 3 ถึง 4 เท่า"

ภาพหน้าจอของการแจ้งเตือน Pull Request ของ GitHub ที่ระบุว่าจำเป็นต้องมีการตรวจสอบและการรวมจะถูกบล็อกจนกว่าการตรวจสอบจะได้รับการแก้ไขสำเร็จ
การรวมคะแนนการช่วยสำหรับการเข้าถึง ประสิทธิภาพ และคะแนน SEO เข้ากับการตั้งค่า Travis กับ Lighthouse CI จะเน้นที่ผลกระทบด้านประสิทธิภาพของคุณลักษณะใหม่ต่อนักพัฒนาที่มีส่วนร่วมทั้งหมด (ที่มาของรูปภาพ) (ตัวอย่างขนาดใหญ่)
  1. คุณได้ทดสอบในพร็อกซีเบราว์เซอร์และเบราว์เซอร์รุ่นเก่าหรือไม่
    การทดสอบใน Chrome และ Firefox นั้นไม่เพียงพอ ดูวิธีการทำงานของเว็บไซต์ของคุณในพร็อกซีเบราว์เซอร์และเบราว์เซอร์รุ่นเก่า ตัวอย่างเช่น UC Browser และ Opera Mini มีส่วนแบ่งการตลาดที่สำคัญในเอเชีย (มากถึง 35% ในเอเชีย) วัดความเร็วอินเทอร์เน็ตโดยเฉลี่ยในประเทศที่คุณสนใจ เพื่อหลีกเลี่ยงความประหลาดใจครั้งใหญ่ที่กำลังจะเกิดขึ้น ทดสอบด้วยการควบคุมปริมาณเครือข่าย และจำลองอุปกรณ์ที่มี DPI สูง BrowserStack นั้นยอดเยี่ยมสำหรับการทดสอบบนอุปกรณ์จริง จากระยะไกล และเสริมด้วยอุปกรณ์จริงสองสามเครื่องในสำนักงานของคุณด้วย — มันคุ้มค่า
  1. คุณได้ทดสอบประสิทธิภาพของหน้า 404 ของคุณหรือไม่?
    ปกติแล้วเราจะไม่คิดซ้ำสองเมื่อพูดถึง 404 หน้า เมื่อไคลเอนต์ร้องขอหน้าที่ไม่มีอยู่บนเซิร์ฟเวอร์ เซิร์ฟเวอร์จะตอบสนองด้วยรหัสสถานะ 404 และหน้า 404 ที่เกี่ยวข้อง มันไม่มีอะไรมากขนาดนั้นหรอกเหรอ?

    ลักษณะสำคัญของการตอบสนอง 404 คือ ขนาดเนื้อหาการตอบสนอง จริงที่ถูกส่งไปยังเบราว์เซอร์ จากการวิจัย 404 หน้าโดย Matt Hobbs คำตอบ 404 ส่วนใหญ่มาจาก favicons ที่หายไป, คำขออัปโหลด WordPress, คำขอ JavaScript ที่ใช้งานไม่ได้, ไฟล์ Manifest รวมถึงไฟล์ CSS และฟอนต์ ทุกครั้งที่ลูกค้าร้องขอทรัพย์สินที่ไม่มีอยู่จริง พวกเขาจะได้รับการตอบกลับ 404 และบ่อยครั้งที่การตอบกลับนั้นมีขนาดใหญ่มาก

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

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

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

    แน่นอน ความยินยอมที่แท้จริงมีแนวโน้มที่จะเปลี่ยนผลกระทบของสคริปต์ที่มีต่อประสิทธิภาพโดยรวม ดังนั้นตามที่ Boris Schapira ระบุไว้ เราอาจต้องการศึกษาโปรไฟล์ประสิทธิภาพเว็บที่แตกต่างกันสองสามอย่าง:

    • ความยินยอมถูกปฏิเสธโดยสิ้นเชิง
    • ความยินยอมถูกปฏิเสธบางส่วน
    • ได้รับความยินยอมอย่างสมบูรณ์
    • ผู้ใช้ไม่ได้ดำเนินการตามข้อความยินยอม (หรือข้อความแจ้งถูกบล็อกโดยตัวบล็อกเนื้อหา)

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

    โดยทั่วไป การพิจารณา ประสิทธิภาพของป๊อปอัป นั้นคุ้มค่า เนื่องจากคุณจะต้องกำหนดออฟเซ็ตแนวนอนหรือแนวตั้งของเหตุการณ์เมาส์ และจัดตำแหน่งป๊อปอัปให้ถูกต้องให้สัมพันธ์กับจุดยึด Noam Rosenthal แบ่งปันการเรียนรู้ของทีม Wikimedia ในบทความ กรณีศึกษาประสิทธิภาพเว็บ: การแสดงตัวอย่างหน้า Wikipedia (มีให้ในรูปแบบวิดีโอและนาทีด้วย)

  3. คุณเก็บ CSS การวินิจฉัยประสิทธิภาพหรือไม่
    แม้ว่าเราจะรวมการตรวจสอบทุกประเภทเพื่อให้แน่ใจว่าโค้ดที่ไม่มีประสิทธิภาพได้รับการปรับใช้ แต่มักจะมีประโยชน์ที่จะทราบแนวคิดสั้นๆ เกี่ยวกับผลไม้ที่ค้างอยู่ต่ำซึ่งสามารถแก้ไขได้ง่าย สำหรับสิ่งนั้น เราสามารถใช้ CSS การวินิจฉัยประสิทธิภาพที่ยอดเยี่ยมของ Tim Kadlec (ได้รับแรงบันดาลใจจากตัวอย่างข้อมูลของ Harry Roberts ซึ่งไฮไลต์รูปภาพที่โหลดแบบ Lazy Loading, รูปภาพที่ไม่มีขนาด, รูปภาพรูปแบบเดิมและสคริปต์ซิงโครนัส

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

    /* Performance Diagnostics CSS */ /* via Harry Roberts. https://twitter.com/csswizardry/status/1346477682544951296 */ img[loading=lazy] { outline: 10px solid red; }
  1. Have you tested the impact on accessibility?
    When the browser starts to load a page, it builds a DOM, and if there is an assistive technology like a screen reader running, it also creates an accessibility tree. The screen reader then has to query the accessibility tree to retrieve the information and make it available to the user — sometimes by default, and sometimes on demand. And sometimes it takes time.

    When talking about fast Time to Interactive, usually we mean an indicator of how soon a user can interact with the page by clicking or tapping on links and buttons. The context is slightly different with screen readers. In that case, fast Time to Interactive means how much time passes by until the screen reader can announce navigation on a given page and a screen reader user can actually hit keyboard to interact.

    Leonie Watson has given an eye-opening talk on accessibility performance and specifically the impact slow loading has on screen reader announcement delays. Screen readers are used to fast-paced announcements and quick navigation, and therefore might potentially be even less patient than sighted users.

    Large pages and DOM manipulations with JavaScript will cause delays in screen reader announcements. A rather unexplored area that could use some attention and testing as screen readers are available on literally every platform (Jaws, NVDA, Voiceover, Narrator, Orca).

  2. Is continuous monitoring set up?
    Having a private instance of WebPagetest is always beneficial for quick and unlimited tests. However, a continuous monitoring tool — like Sitespeed, Calibre and SpeedCurve — with automatic alerts will give you a more detailed picture of your performance. Set your own user-timing marks to measure and monitor business-specific metrics. Also, consider adding automated performance regression alerts to monitor changes over time.

    Look into using RUM-solutions to monitor changes in performance over time. For automated unit-test-alike load testing tools, you can use k6 with its scripting API. Also, look into SpeedTracker, Lighthouse and Calibre.

ชนะอย่างรวดเร็ว

This list is quite comprehensive, and completing all of the optimizations might take quite a while. So, if you had just 1 hour to get significant improvements, what would you do? Let's boil it all down to 17 low-hanging fruits . Obviously, before you start and once you finish, measure results, including Largest Contentful Paint and Time To Interactive on a 3G and cable connection.

  1. Measure the real world experience and set appropriate goals. Aim to be at least 20% faster than your fastest competitor. Stay within Largest Contentful Paint < 2.5s, a First Input Delay < 100ms, Time to Interactive < 5s on slow 3G, for repeat visits, TTI < 2s. Optimize at least for First Contentful Paint and Time To Interactive.
  2. Optimize images with Squoosh, mozjpeg, guetzli, pingo and SVGOMG, and serve AVIF/WebP with an image CDN.
  3. Prepare critical CSS for your main templates, and inline them in the <head> of each template. For CSS/JS, operate within a critical file size budget of max. 170KB gzipped (0.7MB decompressed).
  4. Trim, optimize, defer and lazy-load scripts. Invest in the config of your bundler to remove redundancies and check lightweight alternatives.
  5. Always self-host your static assets and always prefer to self-host third-party assets. Limit the impact of third-party scripts. Use facades, load widgets on interaction and beware of anti-flicker snippets.
  6. Be selective when choosing a framework. For single-page-applications, identify critical pages and serve them statically, or at least prerender them, and use progressive hydration on component-level and import modules on interaction.
  7. Client-side rendering alone isn't a good choice for performance. Prerender if your pages don't change much, and defer the booting of frameworks if you can. If possible, use streaming server-side rendering.
  8. Serve legacy code only to legacy browsers with <script type="module"> and module/nomodule pattern.
  9. Experiment with regrouping your CSS rules and test in-body CSS.
  10. Add resource hints to speed up delivery with faster dns-lookup , preconnect , prefetch , preload and prerender .
  11. Subset web fonts and load them asynchronously, and utilize font-display in CSS for fast first rendering.
  12. Check that HTTP cache headers and security headers are set properly.
  13. Enable Brotli compression on the server. (If that's not possible, at least make sure that Gzip compression is enabled.)
  14. Enable TCP BBR congestion as long as your server is running on the Linux kernel version 4.9+.
  15. Enable OCSP stapling and IPv6 if possible. Always serve an OCSP stapled DV certificate.
  16. Enable HPACK compression for HTTP/2 and move to HTTP/3 if it's available.
  17. Cache assets such as fonts, styles, JavaScript and images in a service worker cache.

Download The Checklist (PDF, Apple Pages)

With this checklist in mind, you should be prepared for any kind of front-end performance project. Feel free to download the print-ready PDF of the checklist as well as an editable Apple Pages document to customize the checklist for your needs:

  • Download the checklist PDF (PDF, 166 KB)
  • Download the checklist in Apple Pages (.pages, 275 KB)
  • Download the checklist in MS Word (.docx, 151 KB)

If you need alternatives, you can also check the front-end checklist by Dan Rublic, the "Designer's Web Performance Checklist" by Jon Yablonski and the FrontendChecklist.

เราไปกันเถอะ!

Some of the optimizations might be beyond the scope of your work or budget or might just be overkill given the legacy code you have to deal with. ไม่เป็นไร! Use this checklist as a general (and hopefully comprehensive) guide, and create your own list of issues that apply to your context. But most importantly, test and measure your own projects to identify issues before optimizing. Happy performance results in 2021, everyone!


A huge thanks to Guy Podjarny, Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Andy Davies, Rachel Andrew, Anselm Hannemann, Barry Pollard, Patrick Hamann, Gideon Pyzer, Andy Davies, Maria Prosvernina, Tim Kadlec, Rey Bango, Matthias Ott, Peter Bowyer, Phil Walton, Mariana Peralta, Pepijn Senders, Mark Nottingham, Jean Pierre Vincent, Philipp Tellis, Ryan Townsend, Ingrid Bergman, Mohamed Hussain SH, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson, Adir Amsalem, Aleksey Kulikov and Rodney Rehm for reviewing this article, as well as our fantastic community which has shared techniques and lessons learned from its work in performance optimization for everybody to use. คุณยอดเยี่ยมจริงๆ!