นี่คือสิ่งที่เกิดขึ้นเมื่อเบราว์เซอร์โหลดเว็บไซต์ที่มี<script>
แท็ก:
- ดึงหน้า HTML (เช่น index.html)
- เริ่มต้นการแยกวิเคราะห์ HTML
- parser พบ
<script>
แท็กที่อ้างอิงไฟล์สคริปต์ภายนอก
- เบราว์เซอร์ร้องขอไฟล์สคริปต์ ในขณะเดียวกันตัวแยกวิเคราะห์จะบล็อกและหยุดการแยกวิเคราะห์ HTML อื่น ๆ ในหน้าของคุณ
- หลังจากนั้นครู่หนึ่งสคริปต์จะถูกดาวน์โหลดและดำเนินการในภายหลัง
- parser แยกวิเคราะห์เอกสาร HTML ที่เหลือต่อไป
ขั้นตอนที่ # 4 ทำให้เกิดประสบการณ์การใช้งานที่ไม่ดี โดยทั่วไปเว็บไซต์ของคุณจะหยุดโหลดจนกว่าคุณจะดาวน์โหลดสคริปต์ทั้งหมด หากมีสิ่งหนึ่งที่ผู้ใช้เกลียดชังก็กำลังรอให้เว็บไซต์โหลด
ทำไมสิ่งนี้ถึงเกิดขึ้นได้?
สคริปต์ใด ๆ สามารถแทรก HTML ของตนเองผ่านทางdocument.write()
หรือการเปลี่ยนแปลง DOM อื่น ๆ นี่หมายความว่าตัวแยกวิเคราะห์ต้องรอจนกว่าสคริปต์จะถูกดาวน์โหลดและดำเนินการก่อนจึงจะสามารถแยกวิเคราะห์ส่วนที่เหลือของเอกสารได้อย่างปลอดภัย ท้ายที่สุดสคริปต์อาจแทรก HTML ของตนเองลงในเอกสาร
อย่างไรก็ตามนักพัฒนาจาวาสคริปต์ส่วนใหญ่จะไม่ใช้ DOM ในขณะที่เอกสารกำลังโหลดอีกต่อไป แต่จะรอจนกว่าเอกสารจะถูกโหลดก่อนที่จะแก้ไข ตัวอย่างเช่น:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>
javascript:
// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});
เนื่องจากเบราว์เซอร์ของคุณไม่ทราบ my-script.js จะไม่แก้ไขเอกสารจนกว่าจะมีการดาวน์โหลดและดำเนินการ parser จะหยุดการแยกวิเคราะห์
คำแนะนำโบราณ
วิธีการแบบเก่าในการแก้ปัญหานี้คือการวาง<script>
แท็กที่ด้านล่างของคุณ<body>
เพราะจะทำให้มั่นใจได้ว่าตัวแยกวิเคราะห์จะไม่ถูกบล็อกจนกว่าจะถึงจุดสิ้นสุด
วิธีการนี้มีปัญหาของตัวเอง: เบราว์เซอร์ไม่สามารถเริ่มดาวน์โหลดสคริปต์จนกว่าเอกสารทั้งหมดจะถูกวิเคราะห์ สำหรับเว็บไซต์ขนาดใหญ่ที่มีสคริปต์และสไตล์ชีทขนาดใหญ่ความสามารถในการดาวน์โหลดสคริปต์โดยเร็วที่สุดเป็นสิ่งที่สำคัญมากสำหรับประสิทธิภาพ หากเว็บไซต์ของคุณไม่โหลดภายใน 2 วินาทีผู้คนจะไปที่เว็บไซต์อื่น
ในโซลูชันที่ดีที่สุดเบราว์เซอร์จะเริ่มดาวน์โหลดสคริปต์ของคุณโดยเร็วที่สุดในขณะเดียวกันก็แยกวิเคราะห์เอกสารที่เหลือของคุณ
แนวทางที่ทันสมัย
วันนี้เบราว์เซอร์รองรับasync
และdefer
คุณลักษณะของสคริปต์ คุณลักษณะเหล่านี้บอกเบราว์เซอร์ว่าปลอดภัยในการแยกวิเคราะห์อย่างต่อเนื่องในขณะที่กำลังดาวน์โหลดสคริปต์
async
<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
สคริปต์ที่มีแอตทริบิวต์ async จะถูกดำเนินการแบบอะซิงโครนัส ซึ่งหมายความว่าสคริปต์จะถูกดำเนินการทันทีที่มีการดาวน์โหลดโดยไม่ปิดกั้นเบราว์เซอร์ในระหว่างนี้
หมายความว่าเป็นไปได้ที่จะดาวน์โหลดและดำเนินการสคริปต์ 2 ก่อนหน้าสคริปต์ 1
ตามhttp://caniuse.com/#feat=script-async , 97.78% ของเบราว์เซอร์ทั้งหมดสนับสนุนสิ่งนี้
Defer
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
สคริปต์ที่มีแอตทริบิวต์ defer จะทำงานตามลำดับ (เช่นสคริปต์แรก 1 จากนั้นสคริปต์ 2) สิ่งนี้จะไม่บล็อกเบราว์เซอร์ด้วย
ซึ่งแตกต่างจากสคริปต์ async สคริปต์การเลื่อนจะดำเนินการหลังจากโหลดเอกสารทั้งหมดแล้วเท่านั้น
ตามhttp://caniuse.com/#feat=script-defer 97.79% ของเบราว์เซอร์ทั้งหมดสนับสนุนสิ่งนี้ 98.06% สนับสนุนอย่างน้อยบางส่วน
หมายเหตุสำคัญเกี่ยวกับความเข้ากันได้ของเบราว์เซอร์: ในบางสถานการณ์ IE <= 9 อาจเรียกใช้สคริปต์ที่เลื่อนออกไปตามลำดับ หากคุณต้องการที่จะสนับสนุนเบราว์เซอร์เหล่านั้นโปรดอ่านนี้เป็นครั้งแรก!
ข้อสรุป
สถานะปัจจุบันของศิลปะคือการใส่สคริปต์ใน<head>
แท็กและใช้async
หรือdefer
คุณลักษณะ วิธีนี้ทำให้สคริปต์ของคุณสามารถดาวน์โหลดได้โดยไม่ต้องปิดกั้นเบราว์เซอร์ของคุณ
สิ่งที่ดีคือเว็บไซต์ของคุณควรโหลดอย่างถูกต้องในเบราว์เซอร์ 2% ที่ไม่รองรับคุณสมบัติเหล่านี้ในขณะที่เร่งความเร็วอีก 98%