ในโมดูลก่อนหน้า เราได้สำรวจทฤษฎีบางอย่างที่อยู่เบื้องหลังเส้นทางการแสดงผลที่สำคัญ และวิธีที่ทรัพยากรที่บล็อกการแสดงผลและบล็อกตัวแยกวิเคราะห์อาจทำให้การแสดงผล หน้าเว็บครั้งแรกล่าช้า ตอนนี้คุณมีความเข้าใจทฤษฎีเบื้องหลัง เรื่องนี้แล้ว จึงพร้อมที่จะเรียนรู้เทคนิคบางอย่างในการเพิ่มประสิทธิภาพเส้นทางการแสดงผลที่สำคัญ
เมื่อหน้าเว็บโหลด ระบบจะอ้างอิงทรัพยากรจำนวนมากภายใน HTML ซึ่งจะทำให้หน้าเว็บมีลักษณะและการจัดวางผ่าน CSS รวมถึงการโต้ตอบผ่าน JavaScript ในโมดูลนี้ เราจะพูดถึงแนวคิดสำคัญหลายอย่างที่เกี่ยวข้องกับ แหล่งข้อมูลเหล่านี้และวิธีที่แหล่งข้อมูลส่งผลต่อเวลาในการโหลดของหน้าเว็บ
การบล็อกการแสดงผล
ดังที่ได้กล่าวไว้ในโมดูลก่อนหน้า CSS เป็นทรัพยากรที่บล็อกการแสดงผล เนื่องจากจะบล็อกไม่ให้เบราว์เซอร์แสดงเนื้อหาใดๆ จนกว่าจะสร้างโมเดลออบเจ็กต์ CSS (CSSOM) เสร็จ เบราว์เซอร์จะบล็อกการแสดงผลเพื่อป้องกันFlash of Unstyled Content (FOUC) ซึ่งไม่พึงประสงค์ในมุมมองประสบการณ์ของผู้ใช้
ในวิดีโอก่อนหน้านี้ มี FOUC สั้นๆ ที่คุณจะเห็นหน้าเว็บโดยไม่มี การจัดรูปแบบใดๆ จากนั้น ระบบจะใช้รูปแบบทั้งหมดเมื่อ CSS ของหน้าเว็บโหลดจากเครือข่ายเสร็จสมบูรณ์ และจะแทนที่หน้าเว็บเวอร์ชันที่ไม่มีรูปแบบด้วยเวอร์ชันที่มีรูปแบบทันที
โดยทั่วไปแล้ว FOUC เป็นสิ่งที่คุณไม่ค่อยเห็น แต่แนวคิดนี้มีความสำคัญที่ควรทำความเข้าใจเพื่อให้ทราบเหตุผลที่เบราว์เซอร์บล็อกการแสดงผลของหน้าเว็บจนกว่าจะดาวน์โหลด CSS และนำไปใช้กับหน้าเว็บ การบล็อกการแสดงผล ไม่จำเป็นต้องเป็นสิ่งที่ไม่พึงประสงค์ แต่คุณควรลดระยะเวลาการบล็อกการแสดงผลโดย การเพิ่มประสิทธิภาพ CSS
การบล็อกโปรแกรมแยกวิเคราะห์
ทรัพยากรที่บล็อกตัวแยกวิเคราะห์จะขัดขวางตัวแยกวิเคราะห์ HTML เช่น องค์ประกอบ <script>
ที่ไม่มีแอตทริบิวต์ async
หรือ defer
เมื่อตัวแยกวิเคราะห์พบองค์ประกอบ
<script>
เบราว์เซอร์จะต้องประเมินและเรียกใช้สคริปต์ก่อน
ดำเนินการแยกวิเคราะห์ HTML ที่เหลือ ซึ่งเป็นไปตามการออกแบบ เนื่องจากสคริปต์อาจ
แก้ไขหรือเข้าถึง DOM ในช่วงเวลาที่ยังสร้างอยู่
<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>
เมื่อใช้ไฟล์ JavaScript ภายนอก (ไม่มี async
หรือ defer
) ตัวแยกวิเคราะห์จะถูกบล็อกตั้งแต่เมื่อพบไฟล์จนกว่าจะดาวน์โหลด แยกวิเคราะห์ และ
ดำเนินการ เมื่อใช้ JavaScript แบบอินไลน์ ระบบจะบล็อกตัวแยกวิเคราะห์ในลักษณะเดียวกันจนกว่าจะแยกวิเคราะห์และเรียกใช้สคริปต์แบบอินไลน์
เครื่องสแกนการโหลดล่วงหน้า
เครื่องสแกนการโหลดล่วงหน้าคือการเพิ่มประสิทธิภาพเบราว์เซอร์ในรูปแบบของตัวแยกวิเคราะห์ HTML รอง
ซึ่งจะสแกนการตอบกลับ HTML ดิบเพื่อค้นหาและดึงข้อมูลทรัพยากร
โดยคาดการณ์ไว้ก่อนที่ตัวแยกวิเคราะห์ HTML หลักจะค้นพบ ตัวอย่างเช่น ตัวสแกนการโหลดล่วงหน้าจะอนุญาตให้เบราว์เซอร์เริ่มดาวน์โหลดทรัพยากรที่ระบุในองค์ประกอบ <img>
ได้ แม้ว่าตัวแยกวิเคราะห์ HTML จะถูกบล็อกขณะดึงข้อมูลและประมวลผลทรัพยากร เช่น CSS และ JavaScript
หากต้องการใช้ประโยชน์จากเครื่องสแกนการโหลดล่วงหน้า คุณควรใส่ทรัพยากรที่สำคัญ ในมาร์กอัป HTML ที่เซิร์ฟเวอร์ส่ง เครื่องสแกนการโหลดล่วงหน้าจะค้นพบรูปแบบการโหลดทรัพยากรต่อไปนี้ไม่ได้
- รูปภาพที่โหลดโดย CSS โดยใช้พร็อพเพอร์ตี้
background-image
การอ้างอิงรูปภาพเหล่านี้อยู่ใน CSS และเครื่องสแกนการโหลดล่วงหน้าจะค้นหาไม่ได้ - สคริปต์ที่โหลดแบบไดนามิกในรูปแบบของมาร์กอัปองค์ประกอบ
<script>
ที่แทรกลงใน DOM โดยใช้ JavaScript หรือโมดูลที่โหลดโดยใช้ dynamicimport()
- HTML ที่แสดงผลในไคลเอ็นต์โดยใช้ JavaScript มาร์กอัปดังกล่าวอยู่ในสตริงภายในทรัพยากร JavaScript และเครื่องสแกนการโหลดล่วงหน้าไม่พบ
@import
การประกาศ CSS
รูปแบบการโหลดทรัพยากรเหล่านี้เป็นทรัพยากรที่ค้นพบในภายหลังทั้งหมด จึงไม่ได้รับประโยชน์จากเครื่องสแกนการโหลดล่วงหน้า หลีกเลี่ยงการใช้คำเหล่านี้ทุกครั้งที่เป็นไปได้ อย่างไรก็ตาม หากหลีกเลี่ยงรูปแบบดังกล่าวไม่ได้ คุณอาจใช้คำใบ้ preload
เพื่อหลีกเลี่ยงความล่าช้าในการค้นพบทรัพยากรได้
CSS
CSS จะกำหนดการนำเสนอและเลย์เอาต์ของหน้าเว็บ ดังที่อธิบายไว้ก่อนหน้านี้ CSS เป็นแหล่งข้อมูลที่บล็อกการแสดงผล ดังนั้นการเพิ่มประสิทธิภาพ CSS อาจส่งผล อย่างมากต่อเวลาในการโหลดหน้าเว็บโดยรวม
การลดขนาด
การลดขนาดไฟล์ CSS จะช่วยลดขนาดไฟล์ของแหล่งข้อมูล CSS ทำให้ดาวน์โหลดได้เร็วขึ้น ซึ่งทำได้โดยหลักๆ คือการนำเนื้อหาออกจากไฟล์ CSS ต้นฉบับ เช่น ช่องว่างและอักขระอื่นๆ ที่มองไม่เห็น และส่งออกผลลัพธ์ไปยังไฟล์ที่เพิ่มประสิทธิภาพใหม่
/* Unminified CSS: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
การลดขนาด CSS ในรูปแบบพื้นฐานที่สุดเป็นการเพิ่มประสิทธิภาพที่มีประสิทธิภาพ ซึ่งอาจช่วยปรับปรุง FCP ของเว็บไซต์ และอาจรวมถึง LCP ในบางกรณีด้วย เครื่องมือต่างๆ เช่น Bundler สามารถทำการเพิ่มประสิทธิภาพนี้ให้คุณโดยอัตโนมัติในการสร้างเวอร์ชันที่ใช้งานจริง
นำ CSS ที่ไม่ได้ใช้ออก
ก่อนที่จะแสดงเนื้อหาใดๆ เบราว์เซอร์จะต้องดาวน์โหลดและแยกวิเคราะห์สไตล์ชีตทั้งหมด เวลาที่ต้องใช้ในการแยกวิเคราะห์ให้เสร็จสมบูรณ์ยังรวมถึงสไตล์ที่ ไม่ได้ใช้ในหน้าปัจจุบันด้วย หากคุณใช้ Bundler ที่รวมแหล่งข้อมูล CSS ทั้งหมดไว้ในไฟล์เดียว ผู้ใช้มีแนวโน้มที่จะดาวน์โหลด CSS มากกว่าที่จำเป็นในการแสดงหน้าปัจจุบัน
หากต้องการค้นหา CSS ที่ไม่ได้ใช้สำหรับหน้าปัจจุบัน ให้ใช้เครื่องมือครอบคลุมใน DevTools ของ Chrome

การนำ CSS ที่ไม่ได้ใช้ออกจะส่งผล 2 อย่าง นอกเหนือจากการลดเวลาในการดาวน์โหลดแล้ว คุณยังได้เพิ่มประสิทธิภาพการสร้างแผนผังการแสดงผลด้วย เนื่องจากเบราว์เซอร์ต้องประมวลผลกฎ CSS น้อยลง
หลีกเลี่ยงการประกาศ @import
CSS
แม้ว่าอาจดูสะดวก แต่คุณควรหลีกเลี่ยง@import
การประกาศใน CSS ดังนี้
/* Don't do this: */
@import url('style.css');
การประกาศ @import
ใน CSS ช่วยให้คุณนำเข้าทรัพยากร CSS ภายนอกจากภายในชีตสไตล์ได้ ซึ่งคล้ายกับลักษณะการทำงานขององค์ประกอบ <link>
ใน HTML ความแตกต่างที่สำคัญระหว่าง 2 วิธีนี้คือองค์ประกอบ <link>
HTML เป็นส่วนหนึ่งของการตอบกลับ HTML จึงค้นพบได้เร็วกว่าไฟล์ CSS ที่ดาวน์โหลดโดยการประกาศ @import
สาเหตุที่เป็นเช่นนี้ก็เพราะว่าระบบจะต้องดาวน์โหลดไฟล์ CSS ที่มีการประกาศ @import
ก่อนจึงจะค้นพบการประกาศดังกล่าวได้ ซึ่งส่งผลให้เกิดสิ่งที่เรียกว่าห่วงโซ่คำขอ ซึ่งในกรณีของ CSS จะทำให้ระยะเวลาที่หน้าเว็บใช้ในการแสดงผลครั้งแรกนานขึ้น
ข้อเสียอีกอย่างคือชีตสไตล์ที่โหลดโดยใช้ประกาศ @import
จะค้นพบไม่ได้โดยเครื่องสแกนการโหลดล่วงหน้า
จึงกลายเป็นทรัพยากรที่บล็อกการแสดงผลซึ่งค้นพบในภายหลัง
<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">
ในกรณีส่วนใหญ่ คุณสามารถแทนที่ @import
ได้โดยใช้องค์ประกอบ
<link rel="stylesheet">
องค์ประกอบ <link>
ช่วยให้ดาวน์โหลดชีตสไตล์ได้พร้อมกันและลดเวลาในการโหลดโดยรวม ซึ่งต่างจากประกาศ @import
ซึ่งจะดาวน์โหลดชีตสไตล์ต่อเนื่องกัน
CSS ที่สำคัญแบบอินไลน์
เวลาที่ใช้ในการดาวน์โหลดไฟล์ CSS อาจเพิ่ม FCP ของหน้าเว็บ การฝัง
สไตล์ที่สำคัญในเอกสารจะ<head>
ไม่จำเป็นต้องส่งคำขอเครือข่ายสำหรับ
ทรัพยากร CSS และหากทำอย่างถูกต้องจะช่วยปรับปรุงเวลาในการโหลดครั้งแรกเมื่อ
แคชของเบราว์เซอร์ของผู้ใช้ยังไม่พร้อม คุณสามารถโหลด CSS ที่เหลือแบบไม่พร้อมกันหรือต่อท้ายองค์ประกอบ <body>
ได้
<head>
<title>Page Title</title>
<!-- ... -->
<style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
<!-- Other page markup... -->
<link rel="stylesheet" href="non-critical.css">
</body>
ข้อเสียคือการแทรก CSS จำนวนมากจะเพิ่มไบต์ในการตอบกลับ HTML เริ่มต้น เนื่องจากมักจะแคชทรัพยากร HTML ได้ไม่นานนักหรือแคชไม่ได้เลย การดำเนินการนี้จึงหมายความว่าระบบจะไม่แคช CSS แบบอินไลน์สำหรับหน้าเว็บต่อๆ ไปที่อาจใช้ CSS เดียวกันในสไตล์ชีตภายนอก ทดสอบและวัดประสิทธิภาพของหน้าเว็บ เพื่อให้แน่ใจว่าการแลกเปลี่ยนนั้นคุ้มค่า
การสาธิต CSS
JavaScript
JavaScript เป็นตัวขับเคลื่อนการโต้ตอบส่วนใหญ่บนเว็บ แต่ก็มีข้อเสีย การจัดส่ง JavaScript มากเกินไปอาจทำให้หน้าเว็บตอบสนองช้าในระหว่างการโหลดหน้าเว็บ และอาจทำให้เกิดปัญหาการตอบสนองที่ทำให้การโต้ตอบช้าลง ซึ่งทั้ง 2 อย่างนี้อาจทำให้ผู้ใช้รู้สึกหงุดหงิด
JavaScript ที่บล็อกการแสดงผล
เมื่อโหลดองค์ประกอบ <script>
โดยไม่มีแอตทริบิวต์ defer
หรือ async
เบราว์เซอร์จะบล็อกการแยกวิเคราะห์และการแสดงผลจนกว่าจะดาวน์โหลด แยกวิเคราะห์ และดำเนินการกับสคริปต์เสร็จสิ้น ในทำนองเดียวกัน สคริปต์แบบอินไลน์จะบล็อกตัวแยกวิเคราะห์จนกว่าจะมีการแยกวิเคราะห์
และดำเนินการสคริปต์
async
เทียบกับ defer
async
และ defer
อนุญาตให้สคริปต์ภายนอกโหลดได้โดยไม่บล็อกตัวแยกวิเคราะห์ HTML
ขณะที่สคริปต์ (รวมถึงสคริปต์ในหน้า) ที่มี type="module"
จะ
เลื่อนออกไปโดยอัตโนมัติ อย่างไรก็ตาม async
และ defer
มีความแตกต่างบางประการที่คุณควรทราบ
สคริปต์ที่โหลดด้วย async
จะได้รับการแยกวิเคราะห์และดำเนินการทันทีเมื่อดาวน์โหลด
ส่วนสคริปต์ที่โหลดด้วย defer
จะได้รับการดำเนินการเมื่อการแยกวิเคราะห์เอกสาร HTML เสร็จสมบูรณ์ ซึ่งจะเกิดขึ้นพร้อมกับเหตุการณ์ DOMContentLoaded
ของเบราว์เซอร์
นอกจากนี้ สคริปต์ async
อาจทำงานไม่เป็นไปตามลำดับ ในขณะที่สคริปต์ defer
จะทำงานตามลำดับที่ปรากฏในมาร์กอัป
การแสดงผลฝั่งไคลเอ็นต์
โดยทั่วไป คุณควรหลีกเลี่ยงการใช้ JavaScript เพื่อแสดงเนื้อหาที่สำคัญหรือองค์ประกอบ LCP ของหน้าเว็บ ซึ่งเรียกว่าการแสดงผลฝั่งไคลเอ็นต์ และเป็นเทคนิค ที่ใช้กันอย่างแพร่หลายในแอปพลิเคชันหน้าเว็บเดียว (SPA)
มาร์กอัปที่แสดงผลโดย JavaScript จะหลีกเลี่ยงเครื่องสแกนการโหลดล่วงหน้า เนื่องจากเครื่องสแกนค้นหาทรัพยากรที่อยู่ในมาร์กอัปที่แสดงผลฝั่งไคลเอ็นต์ไม่ได้ ซึ่งอาจทำให้การดาวน์โหลดทรัพยากรที่สำคัญ เช่น รูปภาพ LCP ล่าช้า เบราว์เซอร์จะเริ่มดาวน์โหลดรูปภาพ LCP หลังจากที่สคริปต์ทำงานและเพิ่มองค์ประกอบลงใน DOM แล้วเท่านั้น ในทางกลับกัน สคริปต์จะดำเนินการได้ก็ต่อเมื่อมีการค้นพบ ดาวน์โหลด และแยกวิเคราะห์แล้วเท่านั้น ซึ่งเรียกว่าเชนคำขอที่สำคัญ และควรหลีกเลี่ยง
นอกจากนี้ การแสดงผลมาร์กอัปโดยใช้ JavaScript มีแนวโน้มที่จะสร้างงานที่ใช้เวลานานมากกว่ามาร์กอัปที่ดาวน์โหลดจากเซิร์ฟเวอร์เพื่อตอบสนองต่อคำขอการนำทาง การใช้การแสดงผล HTML ฝั่งไคลเอ็นต์อย่างกว้างขวางอาจส่งผลเสียต่อ เวลาในการตอบสนองต่อการโต้ตอบ โดยเฉพาะอย่างยิ่งในกรณีที่ DOM ของหน้าเว็บมีขนาดใหญ่มาก ซึ่งจะทำให้เกิดการแสดงผลจำนวนมากเมื่อ JavaScript แก้ไข DOM
การลดขนาด
การลดขนาด JavaScript จะช่วยลดขนาดไฟล์ของทรัพยากรสคริปต์ได้เช่นเดียวกับ CSS ซึ่งจะช่วยให้ดาวน์โหลดได้เร็วขึ้น ทำให้เบราว์เซอร์ไปยัง กระบวนการแยกวิเคราะห์และคอมไพล์ JavaScript ได้เร็วขึ้น
นอกจากนี้ การลดขนาด JavaScript ยังก้าวไปอีกขั้นนอกเหนือจากการลดขนาด ชิ้นงานอื่นๆ เช่น CSS เมื่อย่อ JavaScript แล้ว ระบบจะไม่เพียงนำสิ่งต่างๆ เช่น ช่องว่าง แท็บ และความคิดเห็นออกเท่านั้น แต่ยังย่อสัญลักษณ์ใน JavaScript ต้นฉบับด้วย บางครั้งกระบวนการนี้จะเรียกว่าuglification หากต้องการ ดูความแตกต่าง ให้ใช้ซอร์สโค้ด JavaScript ต่อไปนี้
// Unuglified JavaScript source code:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
เมื่อลดขนาดซอร์สโค้ด JavaScript ก่อนหน้า ผลลัพธ์อาจมีลักษณะคล้ายกับข้อมูลโค้ดต่อไปนี้
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
ในข้อมูลโค้ดก่อนหน้า คุณจะเห็นว่าตัวแปรที่มนุษย์อ่านได้
scriptElement
ในแหล่งที่มาจะย่อเป็น t
เมื่อใช้กับชุดสคริปต์จำนวนมาก
การประหยัดอาจมีนัยสำคัญมากโดยไม่ส่งผลกระทบต่อ
ฟีเจอร์ที่ JavaScript ของเว็บไซต์เวอร์ชันที่ใช้งานจริงมีให้
หากคุณใช้ Bundler เพื่อประมวลผลซอร์สโค้ดของเว็บไซต์ มักจะมีการทำ Uglification โดยอัตโนมัติสำหรับการสร้างเวอร์ชันที่ใช้งานจริง นอกจากนี้ เครื่องมือลดขนาดโค้ด เช่น Terser ยังกำหนดค่าได้สูง ซึ่งช่วยให้คุณปรับแต่ง ความเข้มข้นของอัลกอริทึมการลดขนาดโค้ดเพื่อประหยัดค่าใช้จ่ายได้สูงสุด อย่างไรก็ตาม ค่าเริ่มต้นของเครื่องมือลดขนาดมักจะเพียงพอต่อการสร้างสมดุลที่เหมาะสมระหว่างขนาดเอาต์พุตและการรักษาความสามารถ
การสาธิต JavaScript
ทดสอบความรู้ของคุณ
วิธีที่ดีที่สุดในการโหลดไฟล์ CSS หลายไฟล์ในเบราว์เซอร์คืออะไร
@import
ของ CSS<link>
หลายรายการตัวสแกนการโหลดล่วงหน้าของเบราว์เซอร์ทําอะไรได้บ้าง
<link rel="preload">
ใน
แหล่งข้อมูล HTML
เหตุใดเบราว์เซอร์จึงบล็อกการแยกวิเคราะห์ HTML ชั่วคราวโดยค่าเริ่มต้นเมื่อ ดาวน์โหลดทรัพยากร JavaScript
ถัดไป: ช่วยเบราว์เซอร์ด้วยคำแนะนำเกี่ยวกับทรัพยากร
ตอนนี้คุณทราบแล้วว่าทรัพยากรที่โหลดในองค์ประกอบ <head>
ส่งผลต่อการโหลดหน้าเว็บครั้งแรกและเมตริกต่างๆ อย่างไร
ถึงเวลาที่จะก้าวไปข้างหน้าแล้ว ในโมดูลถัดไป เราจะมาดูคำแนะนำเกี่ยวกับทรัพยากรและวิธีที่คำแนะนำเหล่านี้จะช่วยให้เบราว์เซอร์ได้รับคำแนะนำที่มีประโยชน์ในการเริ่มโหลดทรัพยากรและเปิดการเชื่อมต่อกับเซิร์ฟเวอร์ข้ามต้นทางได้เร็วกว่าที่เบราว์เซอร์จะทำได้หากไม่มีคำแนะนำเหล่านี้