การเพิ่มการโต้ตอบด้วย JavaScript

เผยแพร่: 31 ธันวาคม 2013

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

  • JavaScript สามารถค้นหาและแก้ไข DOM และ CSSOM
  • การบล็อกการเรียกใช้ JavaScript ใน CSSOM
  • JavaScript จะบล็อกการสร้าง DOM เว้นแต่จะมีการประกาศเป็น async อย่างชัดแจ้ง

JavaScript เป็นภาษาแบบไดนามิกที่ทำงานในเบราว์เซอร์และช่วยให้เราเปลี่ยนแปลงลักษณะการทํางานของหน้าเว็บได้เกือบทุกแง่มุม เช่น เราแก้ไขเนื้อหาได้โดยการเพิ่มและนําองค์ประกอบออกจากต้นไม้ DOM, แก้ไขพร็อพเพอร์ตี้ CSSOM ขององค์ประกอบแต่ละรายการ, จัดการอินพุตของผู้ใช้ และอื่นๆ อีกมากมาย มาดูสิ่งที่เกิดขึ้นเมื่อเปลี่ยนตัวอย่าง "Hello World" ก่อนหน้านี้เพื่อเพิ่มสคริปต์สั้นๆ ในบรรทัด

<!DOCTYPE html>
<html>
 
<head>
   
<meta name="viewport" content="width=device-width,initial-scale=1" />
   
<link href="style.css" rel="stylesheet" />
   
<title>Critical Path: Script</title>
 
</head>
 
<body>
   
<p>Hello <span>web performance</span> students!</p>
   
<div><img src="awesome-photo.jpg" /></div>
   
<script>
     
var span = document.getElementsByTagName('span')[0];
      span
.textContent = 'interactive'; // change DOM text content
      span
.style.display = 'inline'; // change CSSOM property
     
// create a new element, style it, and append it to the DOM
     
var loadTime = document.createElement('div');
      loadTime
.textContent = 'You loaded this page on: ' + new Date();
      loadTime
.style.color = 'blue';
      document
.body.appendChild(loadTime);
   
</script>
 
</body>
</html>

ลองใช้

  • JavaScript ช่วยให้เราเข้าถึง DOM และดึงการอ้างอิงไปยังโหนด span ที่ซ่อนอยู่ได้ โหนดดังกล่าวอาจไม่ปรากฏในต้นไม้การแสดงผล แต่ยังคงอยู่ใน DOM จากนั้นเมื่อเรามีข้อมูลอ้างอิงแล้ว เราก็จะเปลี่ยนข้อความ (ผ่าน .textContent) และลบล้างพร็อพเพอร์ตี้สไตล์การแสดงผลที่คำนวณแล้วจาก "ไม่มี" เป็น "แทรกในบรรทัด" ได้ ตอนนี้หน้าเว็บของเราแสดงข้อความว่า "สวัสดี นักเรียนที่มีส่วนร่วม"

  • นอกจากนี้ JavaScript ยังช่วยให้เราสร้าง จัดรูปแบบ ต่อท้าย และนําองค์ประกอบใหม่ใน DOM ออกได้ด้วย ในทางเทคนิคแล้ว หน้าเว็บทั้งหมดอาจเป็นไฟล์ JavaScript ขนาดใหญ่ไฟล์เดียวที่สร้างและจัดสไตล์องค์ประกอบทีละรายการ แม้ว่าวิธีนี้จะใช้ได้ แต่ในทางปฏิบัติแล้วการใช้ HTML และ CSS จะง่ายกว่ามาก ในส่วนที่ 2 ของฟังก์ชัน JavaScript เราจะสร้างองค์ประกอบ div ใหม่ ตั้งค่าเนื้อหาข้อความ จัดรูปแบบ และเพิ่มต่อท้ายส่วนเนื้อหา

ตัวอย่างหน้าเว็บที่แสดงผลในอุปกรณ์เคลื่อนที่

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

อย่างไรก็ตาม แม้ว่า JavaScript จะทําให้เรามีความสามารถมากมาย แต่ก็มีข้อจํากัดเพิ่มเติมมากมายเกี่ยวกับวิธีและเวลาที่หน้าเว็บจะแสดงผล

ก่อนอื่น ให้สังเกตว่าในตัวอย่างก่อนหน้านี้ สคริปต์อินไลน์อยู่ใกล้กับด้านล่างของหน้า เหตุผล คุณควรลองทำดูด้วยตนเอง แต่หากเราย้ายสคริปต์ไปไว้เหนือองค์ประกอบ <span> คุณจะเห็นว่าสคริปต์ไม่ทำงานและบ่นว่าไม่พบการอ้างอิงองค์ประกอบ <span> ในเอกสาร กล่าวคือ getElementsByTagName('span') แสดงผลเป็น null ตัวอย่างนี้แสดงถึงพร็อพเพอร์ตี้ที่สําคัญ: สคริปต์จะทํางาน ณ จุดที่แทรกไว้ในเอกสาร เมื่อตัวแยกวิเคราะห์ HTML พบแท็กสคริปต์ ก็จะหยุดกระบวนการสร้าง DOM ชั่วคราวและส่งการควบคุมไปยังเครื่องมือรันไทม์ JavaScript หลังจากเครื่องมือรันไทม์ JavaScript ทำงานเสร็จแล้ว เบราว์เซอร์จะทำงานต่อจากจุดที่หยุดไว้และสร้าง DOM ต่อ

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

คุณสมบัติอีกอย่างหนึ่งที่ละเอียดอ่อนของการนำสคริปต์มาใช้ในหน้าเว็บคือสคริปต์สามารถอ่านและแก้ไขได้ไม่เพียง DOM เท่านั้น แต่ยังรวมถึงพร็อพเพอร์ตี้ CSSOM ด้วย อันที่จริงแล้ว นั่นคือสิ่งที่เราทําในตัวอย่างเมื่อเปลี่ยนพร็อพเพอร์ตี้การแสดงผลขององค์ประกอบ span จาก none เป็น inline ผลลัพธ์ที่ได้คือ ตอนนี้เรามีภาวะแข่งขัน

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

กล่าวโดยย่อคือ JavaScript เพิ่มการพึ่งพาใหม่จำนวนมากระหว่าง DOM, CSSOM และการเรียกใช้ JavaScript ซึ่งอาจทําให้เบราว์เซอร์ประมวลผลและแสดงผลหน้าเว็บบนหน้าจอล่าช้าอย่างมาก

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

"การเพิ่มประสิทธิภาพเส้นทางการแสดงผลที่สําคัญ" หมายถึงการทำความเข้าใจและการเพิ่มประสิทธิภาพกราฟความเกี่ยวข้องระหว่าง HTML, CSS และ JavaScript ในระดับที่มาก

การบล็อกตัวแยกวิเคราะห์กับ JavaScript แบบอะซิงโครนัส

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

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

<!DOCTYPE html>
<html>
 
<head>
   
<meta name="viewport" content="width=device-width,initial-scale=1" />
   
<link href="style.css" rel="stylesheet" />
   
<title>Critical Path: Script External</title>
 
</head>
 
<body>
   
<p>Hello <span>web performance</span> students!</p>
   
<div><img src="awesome-photo.jpg" /></div>
   
<script src="app.js"></script>
 
</body>
</html>

app.js

var span = document.getElementsByTagName('span')[0];
span
.textContent = 'interactive'; // change DOM text content
span
.style.display = 'inline'; // change CSSOM property
// create a new element, style it, and append it to the DOM
var loadTime = document.createElement('div');
loadTime
.textContent = 'You loaded this page on: ' + new Date();
loadTime
.style.color = 'blue';
document
.body.appendChild(loadTime);

ลองใช้

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

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

ในการดําเนินการนี้ ระบบจะเพิ่มแอตทริบิวต์ async ลงในองค์ประกอบ <script>

<!DOCTYPE html>
<html>
 
<head>
   
<meta name="viewport" content="width=device-width,initial-scale=1" />
   
<link href="style.css" rel="stylesheet" />
   
<title>Critical Path: Script Async</title>
 
</head>
 
<body>
   
<p>Hello <span>web performance</span> students!</p>
   
<div><img src="awesome-photo.jpg" /></div>
   
<script src="app.js" async></script>
 
</body>
</html>

ลองใช้

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

ความคิดเห็น