Front-End Performance 2021: การเพิ่มประสิทธิภาพการจัดส่ง
เผยแพร่แล้ว: 2022-03-10คำแนะนำนี้ได้รับการสนับสนุนอย่างดีจากเพื่อนของเราที่ LogRocket ซึ่งเป็นบริการที่รวม การตรวจสอบประสิทธิภาพของส่วนหน้า การ เล่นซ้ำของเซสชัน และการวิเคราะห์ผลิตภัณฑ์เพื่อช่วยให้คุณสร้างประสบการณ์ลูกค้าที่ดียิ่งขึ้น LogRocket ติดตามตัวชี้วัดหลัก รวมถึง DOM เสร็จสมบูรณ์, เวลาถึงไบต์แรก, การหน่วงเวลาอินพุตครั้งแรก, การใช้ CPU ของไคลเอ็นต์และหน่วยความจำ ทดลองใช้ LogRocket ฟรีวันนี้
สารบัญ
- เตรียมตัวให้พร้อม: การวางแผนและการวัดผล
- การตั้งเป้าหมายที่สมจริง
- การกำหนดสภาพแวดล้อม
- การเพิ่มประสิทธิภาพสินทรัพย์
- สร้างการเพิ่มประสิทธิภาพ
- การเพิ่มประสิทธิภาพการจัดส่ง
- เครือข่าย, HTTP/2, HTTP/3
- การทดสอบและการตรวจสอบ
- ชนะอย่างรวดเร็ว
- ทุกอย่างในหน้าเดียว
- ดาวน์โหลดรายการตรวจสอบ (PDF, Apple Pages, MS Word)
- สมัครรับจดหมายข่าวทางอีเมลของเราเพื่อไม่ให้พลาดคำแนะนำต่อไป
การเพิ่มประสิทธิภาพการจัดส่ง
- เราใช้
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 ให้เร็วขึ้น โดยจะกล่าวถึงรายละเอียดของการแยกวิเคราะห์แบบเก็งกำไร อะซิงโครนัส และการเลื่อนเวลา
- ขี้เกียจโหลดส่วนประกอบราคาแพงด้วย 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 ควรเป็นข้อยกเว้นแทนที่จะเป็นกฎ อาจไม่สมเหตุสมผลที่จะโหลดสิ่งที่คุณต้องการให้คนเห็นอย่างรวดเร็วจริง ๆ เช่น รูปภาพหน้าผลิตภัณฑ์ ภาพฮีโร่ หรือสคริปต์ที่จำเป็นสำหรับการนำทางหลักเพื่อให้โต้ตอบได้
- โหลดภาพไปเรื่อย
คุณยังสามารถโหลดแบบ Lazy Loading ไปอีกระดับได้ด้วยการเพิ่มการโหลดภาพแบบโปรเกรสซีฟลงในหน้าเว็บของคุณ เช่นเดียวกับ Facebook, Pinterest, Medium และ Wolt คุณสามารถโหลดรูปภาพคุณภาพต่ำหรือแม้แต่ภาพเบลอก่อน จากนั้นเมื่อหน้าเว็บยังคงโหลด ให้แทนที่ด้วยเวอร์ชันคุณภาพเต็มโดยใช้เทคนิค BlurHash หรือ LQIP (ตัวยึดตำแหน่งรูปภาพคุณภาพต่ำ) เทคนิค.ความคิดเห็นจะต่างกันออกไปหากเทคนิคเหล่านี้ปรับปรุงประสบการณ์ผู้ใช้หรือไม่ แต่จะช่วยปรับปรุงเวลาในการใช้ First Contentful Paint ได้อย่างแน่นอน เรายังทำให้เป็นอัตโนมัติได้โดยใช้ SQIP ที่สร้างเวอร์ชันคุณภาพต่ำของรูปภาพเป็นตัวยึด SVG หรือตัวยึดตำแหน่งรูปภาพแบบไล่ระดับสีที่มีการไล่ระดับสีแบบเส้นตรง CSS
ตัวยึดตำแหน่งเหล่านี้สามารถฝังอยู่ภายใน HTML ได้ เนื่องจากจะบีบอัดได้ดีด้วยวิธีการบีบอัดข้อความ ในบทความของเขา Dean Hume ได้อธิบายวิธีการนำเทคนิคนี้ไปใช้โดยใช้ Intersection Observer
รั้งท้าย? หากเบราว์เซอร์ไม่รองรับการสังเกตทางแยก เราก็ยังสามารถโหลดโพลีฟิลหรือโหลดรูปภาพได้ทันที และมีแม้กระทั่งห้องสมุดสำหรับมัน
ต้องการที่จะไปนักเล่น? คุณสามารถติดตามรูปภาพของคุณและใช้รูปร่างและขอบดั้งเดิมเพื่อสร้างตัวยึด SVG น้ำหนักเบา โหลดรูปภาพก่อน จากนั้นเปลี่ยนจากรูปภาพเวกเตอร์ของตัวยึดตำแหน่งเป็นรูปภาพบิตแมป (โหลดแล้ว)
- คุณเลื่อนการแสดงผลด้วย
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
แทนค่า defaultmargin-left: auto;
,margin-right: auto;
และความกว้างที่ประกาศไว้ ช่องว่างภายในช่วยให้องค์ประกอบล้นกล่องเนื้อหาและป้อนช่องว่างภายในโดยไม่ต้องออกจากรูปแบบกล่องโดยรวมและถูกตัดออกนอกจากนี้ พึงระลึกไว้เสมอว่าคุณอาจแนะนำ
contain-intrinsic-size
บางอย่างเมื่อเนื้อหาใหม่ได้รับการเร น เดอร์ในที่สุด ดังนั้นจึงควรใช้Thijs Terluin มีรายละเอียดเพิ่มเติมเกี่ยวกับทั้งสองคุณสมบัติและวิธีคำนวณ
contain-intrinsic-size
โดยเบราว์เซอร์ Malte Ubl แสดงให้เห็นว่าคุณสามารถคำนวณได้อย่างไรและวิดีโออธิบายสั้น ๆ โดย Jake และ Surma อธิบายว่ามันทำงานอย่างไรและถ้าคุณต้องการความละเอียดมากขึ้น ด้วย CSS Containment คุณสามารถข้ามงานเลย์เอาต์ สไตล์ และสีสำหรับผู้สืบทอดของโหนด DOM หากคุณต้องการเพียงขนาด การจัดตำแหน่ง หรือสไตล์ที่คำนวณบนองค์ประกอบอื่น — หรือองค์ประกอบอยู่ในขณะนี้ ปิดผ้าใบ
- คุณเลื่อนการถอดรหัสด้วย
decoding="async"
หรือไม่
บางครั้งเนื้อหาอาจปรากฏนอกจอ แต่เราต้องการให้แน่ใจว่าจะพร้อมใช้งานเมื่อลูกค้าต้องการ — ไม่ควรปิดกั้นสิ่งใดในเส้นทางที่สำคัญ แต่เป็นการถอดรหัสและแสดงผลแบบอะซิงโครนัส เราสามารถใช้decoding="async"
เพื่อให้เบราว์เซอร์ได้รับอนุญาตให้ถอดรหัสรูปภาพจากเธรดหลัก หลีกเลี่ยงผลกระทบต่อผู้ใช้ของเวลา CPU ที่ใช้ในการถอดรหัสรูปภาพ (ผ่าน Malte Ubl):<img decoding="async" … />
อีกทางหนึ่ง สำหรับรูปภาพนอกจอ เราสามารถแสดงตัวยึดตำแหน่งก่อน และเมื่อรูปภาพนั้นอยู่ภายในวิวพอร์ต โดยใช้ IntersectionObserver จะเรียกเครือข่ายให้ดาวน์โหลดรูปภาพในพื้นหลัง นอกจากนี้ เราสามารถเลื่อนการเรนเดอร์ออกไปจนกว่าจะถอดรหัสด้วย img.decode() หรือดาวน์โหลดรูปภาพหากไม่มี Image Decode API
เมื่อทำการเรนเดอร์รูปภาพ เราสามารถใช้แอนิเมชั่นเฟดอินได้ เป็นต้น Katie Hempenius และ Addy Osmani แบ่งปันข้อมูลเชิงลึกเพิ่มเติมในการพูดคุย Speed at Scale: เคล็ดลับและเทคนิคเกี่ยวกับประสิทธิภาพของเว็บจากสนามเพลาะ
- คุณสร้างและให้บริการ 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 ในขณะนี้
- ทดลองจัดกลุ่มกฎ 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
- คุณสตรีมการตอบสนองหรือไม่
บ่อยครั้งที่ถูกลืมและละเลย สตรีมมีอินเทอร์เฟซสำหรับการอ่านหรือเขียนกลุ่มข้อมูลแบบอะซิงโครนัส เฉพาะชุดย่อยเท่านั้นที่อาจพร้อมใช้งานในหน่วยความจำ ณ เวลาที่กำหนด โดยพื้นฐานแล้ว พวกเขาอนุญาตให้เพจที่สร้างคำขอดั้งเดิมเริ่มทำงานด้วยการตอบกลับทันทีที่มีข้อมูลก้อนแรก และใช้ตัวแยกวิเคราะห์ที่ได้รับการปรับให้เหมาะสมสำหรับการสตรีมเพื่อแสดงเนื้อหาแบบค่อยเป็นค่อยไปเราสามารถสร้างสตรีมเดียวจากหลายแหล่ง ตัวอย่างเช่น แทนที่จะให้บริการเชลล์ 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
- พิจารณาให้ส่วนประกอบของคุณทราบถึงการเชื่อมต่อ
ข้อมูลอาจมีราคาแพงและด้วยเพย์โหลดที่เพิ่มขึ้น เราจำเป็นต้องเคารพผู้ใช้ที่เลือกใช้การประหยัดข้อมูลขณะเข้าถึงเว็บไซต์หรือแอปของเรา ส่วนหัวคำขอคำใบ้ไคลเอ็นต์บันทึกข้อมูลช่วยให้เราปรับแต่งแอปพลิเคชันและเพย์โหลดสำหรับผู้ใช้ที่จำกัดต้นทุนและประสิทธิภาพในความเป็นจริง คุณสามารถเขียนคำขอใหม่สำหรับรูปภาพ 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 ราคาแพง
-
- พิจารณาทำให้ส่วนประกอบของคุณรับรู้หน่วยความจำของอุปกรณ์
การเชื่อมต่อเครือข่ายทำให้เรามีมุมมองเดียวในบริบทของผู้ใช้ ยิ่งไปกว่านั้น คุณยังสามารถปรับทรัพยากรแบบไดนามิกตามหน่วยความจำของอุปกรณ์ที่มีได้ด้วย Device Memory APInavigator.deviceMemory
จะคืนค่า RAM ที่อุปกรณ์มีหน่วยเป็นกิกะไบต์ โดยปัดเศษเป็นกำลังสองที่ใกล้ที่สุด API ยังมีคุณลักษณะ Client Hints Header,Device-Memory
ที่รายงานค่าเดียวกันโบนัส : Umar Hansa จะแสดงวิธีเลื่อนเวลาสคริปต์ราคาแพงด้วยการนำเข้าแบบไดนามิกเพื่อเปลี่ยนประสบการณ์ตามหน่วยความจำของอุปกรณ์ การเชื่อมต่อเครือข่าย และการทำงานพร้อมกันของฮาร์ดแวร์
- อุ่นเครื่องการเชื่อมต่อเพื่อเพิ่มความเร็วในการจัดส่ง
ใช้คำแนะนำทรัพยากรเพื่อประหยัดเวลาในdns-prefetch
(ซึ่งทำการค้นหา DNS ในพื้นหลัง) การpreconnect
(ซึ่งขอให้เบราว์เซอร์เริ่มการเชื่อมต่อแฮนด์เชค (DNS, TCP, TLS) ในพื้นหลัง) การprefetch
(ซึ่งถามเบราว์เซอร์ เพื่อขอทรัพยากร) และpreload
(ซึ่งดึงทรัพยากรล่วงหน้าโดยไม่ต้องดำเนินการใด ๆ เหนือสิ่งอื่นใด) รองรับเบราว์เซอร์รุ่นใหม่ได้ดี และรองรับ Firefox เร็วๆ นี้จำ
prerender
? คำใบ้ทรัพยากรใช้เพื่อแจ้งให้เบราว์เซอร์สร้างทั้งหน้าในพื้นหลังสำหรับการนำทางครั้งต่อไป ปัญหาการใช้งานค่อนข้างมีปัญหา ตั้งแต่หน่วยความจำขนาดใหญ่และการใช้แบนด์วิธ ไปจนถึง Hit การวิเคราะห์ที่ลงทะเบียนและการแสดงโฆษณาหลายครั้งไม่น่าแปลกใจเลยที่มันถูกเลิกใช้แล้ว แต่ทีม Chrome ได้นำมันกลับมาเป็นกลไก NoState Prefetch อันที่จริง Chrome ถือว่าคำใบ้การแสดงผล
prerender
เป็น NoState Prefetch แทน ดังนั้นเราจึงยังคงใช้งานได้ในปัจจุบัน ดังที่ Katie Hempenius อธิบายไว้ในบทความนั้น "เช่นการแสดงผลล่วงหน้า NoState Prefetch จะดึงทรัพยากรล่วงหน้า แต่ต่างจากการแสดงผลล่วงหน้าตรงที่ จะไม่รัน JavaScript หรือแสดงผลส่วนใดส่วนหนึ่งของหน้าล่วงหน้า"NoState Prefetch ใช้หน่วยความจำประมาณ 45MiB และทรัพยากรย่อยที่ถูกดึงออกมาจะถูกดึงข้อมูลด้วย
IDLE
Net Priority ตั้งแต่ Chrome 69 NoState Prefetch จะเพิ่มส่วนหัว Purpose: Prefetch ให้กับคำขอทั้งหมดเพื่อให้แตกต่างจากการเรียกดูปกตินอกจากนี้ ให้ระวังตัวเลือกการแสดงผลล่วงหน้าและพอร์ทัล ซึ่งเป็นความพยายามครั้งใหม่ในการพรีเรนเดอร์ที่คำนึงถึงความเป็นส่วนตัว ซึ่งจะให้การ
preview
เนื้อหาสำหรับการนำทางที่ราบรื่นการใช้คำแนะนำทรัพยากรอาจ เป็นวิธีที่ง่ายที่สุดในการเพิ่มประสิทธิภาพ และทำงานได้ดีแน่นอน ใช้อะไรเมื่อไหร่? ตามที่ Addy Osmani ได้อธิบายไว้ การโหลดทรัพยากรล่วงหน้านั้นสมเหตุสมผล ซึ่งเราทราบดีว่ามีแนวโน้มที่จะถูกใช้ในหน้าปัจจุบัน และสำหรับการนำทางในอนาคตตามขอบเขตการนำทางที่หลากหลาย เช่น ชุด Webpack ที่จำเป็นสำหรับหน้าที่ผู้ใช้ยังไม่ได้เข้าชม
บทความของ Addy เรื่อง "Loading Priorities in Chrome" แสดงให้เห็น ว่า Chrome ตีความคำแนะนำทรัพยากรอย่างไร ดังนั้น เมื่อคุณได้ตัดสินใจแล้วว่าเนื้อหาใดมีความสำคัญต่อการแสดงผล คุณสามารถกำหนดลำดับความสำคัญสูงให้กับเนื้อหาเหล่านั้นได้ หากต้องการดูลำดับความสำคัญของคำขอ คุณสามารถเปิดใช้งานคอลัมน์ "ลำดับความสำคัญ" ในตารางคำขอเครือข่าย Chrome DevTools (เช่นเดียวกับ Safari)
ส่วนใหญ่ในทุกวันนี้ เราจะใช้การ
preconnect
และdns-prefetch
เป็น อย่างน้อย และเราจะระมัดระวังในการใช้prefetch
,preload
และprerender
โปรดทราบว่าแม้จะมีการpreconnect
และdns-prefetch
เบราว์เซอร์ก็มีการจำกัดจำนวนโฮสต์ที่จะค้นหา/เชื่อมต่อแบบคู่ขนาน ดังนั้นจึงเป็นเดิมพันที่ปลอดภัยในการสั่งซื้อตามลำดับความสำคัญ ( ขอบคุณ Philip Tellis! )เนื่องจาก แบบอักษร มักจะเป็นทรัพย์สินที่สำคัญบนหน้าเว็บ บางครั้งจึงเป็นความคิดที่ดีที่จะขอให้เบราว์เซอร์ดาวน์โหลดแบบอักษรที่สำคัญด้วยการ
preload
อย่างไรก็ตาม ให้ตรวจสอบอีกครั้งว่ามันช่วยให้ประสิทธิภาพการทำงานจริงหรือไม่ เนื่องจากมีปริศนาเกี่ยวกับลำดับความสำคัญเมื่อโหลดฟอนต์ไว้ล่วงหน้า: เนื่องจากpreload
ถูกมองว่ามีความสำคัญสูง จึงสามารถกระโดดข้ามทรัพยากรที่สำคัญยิ่งกว่า เช่น CSS ที่สำคัญได้ ( ขอบคุณ แบร์รี่! )<!-- 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)" />
เนื่องจาก
<link rel="preload">
ยอมรับแอตทริบิวต์ของmedia
คุณจึงเลือกดาวน์โหลดทรัพยากรโดยอิงตามกฎการสืบค้น@media
ได้ตามที่แสดงด้านบนนอกจากนี้ เราสามารถใช้
imagesrcset
และimagesizes
แอตทริบิวต์เพื่อโหลดภาพฮีโร่ที่ค้นพบช้าไว้ล่วงหน้าได้เร็วขึ้น หรือภาพใดๆ ที่โหลดผ่าน JavaScript เช่น โปสเตอร์ภาพยนตร์:<!-- 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>
นอกจากนี้เรายังสามารถ โหลด JSON ล่วงหน้า เป็น fetch ได้ ดังนั้นจึงถูกค้นพบก่อนที่ JavaScript จะได้รับการร้องขอ:
<!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>
เรายังโหลด JavaScript แบบไดนามิกได้อย่างมีประสิทธิภาพสำหรับการดำเนินการสคริปต์แบบ Lazy
/* 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);
Gotchas สองสามข้อที่ต้องจำไว้: การ
preload
นั้นดีสำหรับการย้ายเวลาเริ่มต้นการดาวน์โหลดของเนื้อหาให้ใกล้กับคำขอเริ่มต้นมากขึ้น แต่เนื้อหาที่โหลดล่วงหน้าจะลงจอดใน แคชหน่วยความจำ ซึ่งเชื่อมโยงกับเพจที่ส่งคำขอpreload
ทำงานได้ดีกับแคช HTTP: คำขอเครือข่ายจะไม่ถูกส่งหากรายการนั้นมีอยู่แล้วในแคช HTTPดังนั้นจึงมีประโยชน์สำหรับทรัพยากรที่ค้นพบในช่วงปลาย อิมเมจฮีโร่ที่โหลดผ่าน
background-image
, CSS ที่สำคัญในอินไลน์ (หรือ JavaScript) ที่สำคัญ และการโหลดล่วงหน้าส่วนที่เหลือของ CSS (หรือ JavaScript)แท็ก
preload
สามารถเริ่มต้นการโหลดล่วงหน้าได้ก็ต่อเมื่อเบราว์เซอร์ได้รับ HTML จากเซิร์ฟเวอร์และตัวแยกวิเคราะห์ lookahead พบแท็กpreload
แล้ว การโหลดล่วงหน้าผ่านส่วนหัว HTTP อาจเร็วขึ้นเล็กน้อย เนื่องจากเราไม่รอให้เบราว์เซอร์แยกวิเคราะห์ HTML เพื่อเริ่มต้นคำขอEarly Hints จะช่วยได้มากยิ่งกว่าเดิม โดยเปิดใช้งานการโหลดล่วงหน้าก่อนที่จะส่งส่วนหัวการตอบกลับสำหรับ HTML (บนแผนงานใน Chromium, Firefox) นอกจากนี้ Priority Hints จะช่วยเราระบุลำดับความสำคัญในการโหลดสคริปต์
ระวัง : หากคุณกำลังใช้
preload
as
กำหนด ไว้หรือไม่มีการโหลดใดๆ รวมทั้งฟอนต์ที่โหลดไว้ล่วงหน้าโดยไม่มีแอตทริบิวต์crossorigin
จะถูกดึงข้อมูลสองครั้ง หากคุณกำลังใช้prefetch
ให้ระวังปัญหาส่วนหัวAge
ใน Firefox
- ใช้บริการพนักงานบริการสำหรับการแคชและเครือข่ายสำรอง
ไม่มีการเพิ่มประสิทธิภาพการทำงานบนเครือข่ายได้เร็วกว่าแคชที่จัดเก็บไว้ในเครื่องของผู้ใช้ (แต่ก็มีข้อยกเว้น) หากเว็บไซต์ของคุณทำงานบน HTTPS เราสามารถแคชสินทรัพย์แบบคงที่ในแคชของพนักงานบริการและจัดเก็บทางเลือกออฟไลน์ (หรือแม้แต่หน้าออฟไลน์) และดึงข้อมูลจากเครื่องของผู้ใช้ แทนที่จะไปที่เครือข่ายตามที่ Phil Walton แนะนำ เราสามารถส่งเพย์โหลด HTML ที่มีขนาดเล็กลงได้ โดยสร้างการตอบกลับโดยทางโปรแกรม พนักงานบริการสามารถขอข้อมูลขั้นต่ำที่ต้องการจากเซิร์ฟเวอร์ได้ (เช่น เนื้อหา HTML บางส่วน ไฟล์ Markdown ข้อมูล JSON เป็นต้น) จากนั้น โปรแกรมจะแปลง ข้อมูลนั้นเป็นเอกสาร HTML แบบเต็มโดยทางโปรแกรม ดังนั้น เมื่อผู้ใช้เยี่ยมชมไซต์และติดตั้งพนักงานบริการแล้ว ผู้ใช้จะไม่ขอหน้า HTML แบบเต็มอีกเลย ผลกระทบด้านประสิทธิภาพค่อนข้างน่าประทับใจ
รองรับเบราว์เซอร์? พนักงานบริการได้รับการสนับสนุนอย่างกว้างขวางและทางเลือกก็คือเครือข่ายอยู่ดี ช่วยเพิ่มประสิทธิภาพการ ทำงาน ? โอ้ใช่มันไม่ และมันก็ดีขึ้นเรื่อยๆ เช่น การดึงข้อมูลพื้นหลังที่อนุญาตให้อัปโหลด/ดาวน์โหลดพื้นหลังผ่านพนักงานบริการได้เช่นกัน
มีหลายกรณีการใช้งานสำหรับผู้ปฏิบัติงานบริการ ตัวอย่างเช่น คุณสามารถใช้คุณลักษณะ "บันทึกสำหรับออฟไลน์" จัดการรูปภาพที่เสียหาย แนะนำการส่งข้อความระหว่างแท็บ หรือจัดเตรียมกลยุทธ์การแคชที่แตกต่างกันตามประเภทคำขอ โดยทั่วไป กลยุทธ์ทั่วไปที่น่าเชื่อถือคือการจัดเก็บเปลือกแอปในแคชของพนักงานบริการพร้อมกับหน้าที่สำคัญบางหน้า เช่น หน้าออฟไลน์ หน้าแรก และหน้าอื่นๆ ที่อาจมีความสำคัญในกรณีของคุณ
มี gotchas สองสามข้อที่ต้องจำไว้ เมื่อมีพนักงานบริการอยู่แล้ว เราต้องระวังคำขอช่วงใน Safari (หากคุณใช้ Workbox สำหรับพนักงานบริการ จะมีโมดูลคำขอช่วง) หากคุณเคยสะดุดกับ
DOMException: Quota exceeded.
ในคอนโซลของเบราว์เซอร์ จากนั้นดูบทความของ Gerardo เมื่อ 7KB เท่ากับ 7MBตามที่ Gerardo เขียนว่า “หากคุณกำลังสร้างเว็บแอปแบบโปรเกรสซีฟและกำลังประสบกับพื้นที่จัดเก็บแคชที่บวมเมื่อพนักงานบริการของคุณแคชสินทรัพย์แบบคงที่ที่ให้บริการจาก CDN ตรวจสอบให้แน่ใจว่าส่วนหัวการตอบสนอง CORS ที่เหมาะสมสำหรับทรัพยากรข้ามต้นทางนั้นมีอยู่ คุณจะไม่แคชการตอบกลับแบบทึบ กับพนักงานบริการของคุณโดยไม่ตั้งใจ คุณเลือกใช้เนื้อหารูปภาพข้ามต้นทางในโหมด CORS โดยเพิ่มแอตทริบิวต์
crossorigin
ลงในแท็ก<img>
”มี แหล่งข้อมูลดีๆ มากมาย ในการเริ่มต้นกับพนักงานบริการ:
- Service Worker Mindset ซึ่งช่วยให้คุณเข้าใจว่าพนักงานบริการทำงานอย่างไรเบื้องหลังและสิ่งที่ต้องทำความเข้าใจเมื่อสร้าง
- Chris Ferdinandi มีบทความดีๆ มากมายเกี่ยวกับพนักงานบริการ ซึ่งจะอธิบายวิธีสร้างแอปพลิเคชันออฟไลน์และครอบคลุมสถานการณ์ต่างๆ ตั้งแต่การบันทึกหน้าที่ดูล่าสุดแบบออฟไลน์ ไปจนถึงการตั้งค่าวันหมดอายุสำหรับรายการในแคชของพนักงานบริการ
- ข้อผิดพลาดของพนักงานบริการและแนวทางปฏิบัติที่ดีที่สุด พร้อมเคล็ดลับบางประการเกี่ยวกับขอบเขต ทำให้การลงทะเบียนพนักงานบริการและการแคชพนักงานบริการล่าช้า
- ซีรีส์ยอดเยี่ยมโดย Ire Aderinokun เรื่อง "ออฟไลน์ก่อน" กับ Service Worker พร้อมกลยุทธ์ในการพรีแคชเปลือกแอป
- พนักงานบริการ: บทนำพร้อมคำแนะนำที่นำไปใช้ได้จริงเกี่ยวกับวิธีการใช้พนักงานบริการเพื่อประสบการณ์ออฟไลน์ที่สมบูรณ์ การซิงค์ในเบื้องหลังเป็นระยะ และการแจ้งเตือนแบบพุช
- การอ้างอิงถึงตำราออฟไลน์ของ Jake Archibald ที่ดีพร้อมสูตรอาหารมากมายเกี่ยวกับวิธีการอบพนักงานบริการของคุณเอง
- Workbox คือชุดของไลบรารีพนักงานบริการที่สร้างขึ้นโดยเฉพาะสำหรับการสร้างเว็บแอปแบบโปรเกรสซีฟ
- คุณใช้งานเซิร์ฟเวอร์ของผู้ปฏิบัติงานบน CDN/Edge เช่น สำหรับการทดสอบ A/B หรือไม่
ณ จุดนี้ เราค่อนข้างคุ้นเคยกับการเรียกใช้งานบริการบนไคลเอนต์ แต่ด้วยการใช้ CDN บนเซิร์ฟเวอร์ เราสามารถใช้สิ่งเหล่านี้เพื่อปรับแต่งประสิทธิภาพบนขอบได้เช่นกันตัวอย่างเช่น ในการทดสอบ A/B เมื่อ HTML จำเป็นต้องเปลี่ยนเนื้อหาสำหรับผู้ใช้ที่แตกต่างกัน เราสามารถใช้ Service Workers บนเซิร์ฟเวอร์ CDN เพื่อจัดการกับตรรกะ นอกจากนี้เรายังสามารถสตรีมการเขียน HTML ใหม่เพื่อเพิ่มความเร็วให้กับไซต์ที่ใช้ Google Fonts
- เพิ่มประสิทธิภาพการเรนเดอร์
เมื่อใดก็ตามที่แอปพลิเคชันอืดก็สังเกตเห็นได้ทันที ดังนั้นเราจึงต้องตรวจสอบให้แน่ใจว่าไม่มีการกระตุกเมื่อเลื่อนหน้าหรือเมื่อองค์ประกอบเป็นภาพเคลื่อนไหว และคุณเข้าถึง 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 ถูกต้อง
หมายเหตุ : การเปลี่ยนแปลงในเลเยอร์ที่ประกอบด้วย GPU นั้นมีราคาน้อยที่สุด ดังนั้นหากคุณหลีกเลี่ยงได้ด้วยการเรียกใช้การสร้างองค์ประกอบผ่าน
opacity
และtransform
เท่านั้น คุณก็จะมาถูกทาง Anna Migas ได้ให้คำแนะนำที่เป็นประโยชน์มากมายในการพูดคุยของเธอเกี่ยวกับ Debugging UI Rendering Performance ด้วย และเพื่อให้เข้าใจวิธีการดีบักประสิทธิภาพการระบายสีใน DevTools ให้ตรวจสอบวิดีโอการตรวจสอบประสิทธิภาพของ Paint ของ Umar - คุณได้ปรับให้เหมาะสมสำหรับประสิทธิภาพที่รับรู้แล้วหรือไม่?
แม้ว่าลำดับขององค์ประกอบที่ปรากฏบนหน้าเว็บ และกลยุทธ์ในการแสดงเนื้อหาไปยังเบราว์เซอร์มีความสำคัญอย่างไร เราไม่ควรประเมินบทบาทของประสิทธิภาพที่รับรู้ต่ำเกินไปเช่นกัน แนวคิดนี้เกี่ยวข้องกับแง่มุมทางจิตวิทยาของการรอ โดยพื้นฐานแล้วทำให้ลูกค้าไม่ว่างหรือมีส่วนร่วมในขณะที่มีอย่างอื่นเกิดขึ้น นั่นคือจุดเริ่มต้นของการจัดการการรับรู้ การเริ่มต้นยึดเอาเสียก่อน การสำเร็จก่อนกำหนด และการจัดการความอดทนมันไม่สิ่งที่ทุกคนหมายถึงอะไร? ขณะโหลดเนื้อหา เราสามารถพยายามนำ หน้าลูกค้าหนึ่งก้าว เสมอ ดังนั้นประสบการณ์จะรู้สึกรวดเร็วในขณะที่มีเบื้องหลังค่อนข้างมาก เพื่อให้ลูกค้ามีส่วนร่วม เราสามารถทดสอบหน้าจอโครงกระดูก (สาธิตการใช้งาน) แทนการโหลดตัวบ่งชี้ เพิ่มการเปลี่ยน/ภาพเคลื่อนไหว และโดยทั่วไปจะโกง UX เมื่อไม่มีอะไรมากไปกว่านี้เพื่อเพิ่มประสิทธิภาพ
ในกรณีศึกษาของพวกเขาเกี่ยวกับ The Art of UI Skeletons Kumar McMillan จะแบ่งปันแนวคิดและเทคนิคบางอย่างเกี่ยวกับวิธีจำลองรายการแบบไดนามิก ข้อความ และหน้าจอสุดท้าย ตลอดจนวิธีพิจารณาการคิด โครงกระดูก ด้วย React
ระวัง: หน้าจอโครงกระดูกควรได้รับการทดสอบก่อนที่จะปรับใช้ เนื่องจากการทดสอบบางอย่างแสดงให้เห็นว่าหน้าจอโครงกระดูกสามารถทำงานได้แย่ที่สุดในเมตริกทั้งหมด
- คุณป้องกันการเลื่อนเค้าโครงและทาสีใหม่หรือไม่
ในขอบเขตของประสิทธิภาพที่รับรู้ได้ หนึ่งในประสบการณ์ที่ก่อกวนมากกว่านั้นคือการ เลื่อนเล ย์เอาต์ หรือการรี โฟ ลว์ ที่เกิดจากรูปภาพและวิดีโอที่ปรับขนาด แบบอักษรของเว็บ โฆษณาที่แทรก หรือสคริปต์ที่ค้นพบในช่วงหลังซึ่งเติมส่วนประกอบด้วยเนื้อหาจริง ด้วยเหตุนี้ ลูกค้าอาจเริ่มอ่านบทความเพียงเพื่อจะขัดจังหวะโดยเลย์เอาต์ที่อยู่เหนือพื้นที่อ่าน ประสบการณ์มักจะเกิดขึ้นอย่างกะทันหันและค่อนข้างสับสน และนั่นอาจเป็นกรณีของลำดับความสำคัญในการโหลดที่ต้องพิจารณาใหม่ชุมชนได้พัฒนาเทคนิคและวิธีแก้ปัญหาสองสามข้อเพื่อหลีกเลี่ยงการไหลซ้ำ โดยทั่วไป เป็นความคิดที่ดีที่จะ หลีกเลี่ยงการแทรกเนื้อหาใหม่เหนือเนื้อหาที่มีอยู่ เว้นแต่จะเกิดขึ้นเพื่อตอบสนองต่อการโต้ตอบของผู้ใช้ ตั้งค่าแอตทริบิวต์ 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, HTTP/3
- การทดสอบและการตรวจสอบ
- ชนะอย่างรวดเร็ว
- ทุกอย่างในหน้าเดียว
- ดาวน์โหลดรายการตรวจสอบ (PDF, Apple Pages, MS Word)
- สมัครรับจดหมายข่าวทางอีเมลของเราเพื่อไม่ให้พลาดคำแนะนำต่อไป