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

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

สรุป

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

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

<!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 และดึงการอ้างอิงไปยังโหนดช่วงที่ซ่อนอยู่ได้ โหนดอาจไม่ปรากฏในโครงสร้างการแสดงผล แต่ยังคงอยู่ใน DOM จากนั้น เมื่อเรามีข้อมูลอ้างอิงแล้ว เราก็จะเปลี่ยนข้อความของข้อมูลอ้างอิงนั้น (ผ่าน .textContent) และแม้แต่ลบล้างคุณสมบัติรูปแบบการแสดงผลที่คำนวณแล้วจาก "none" เป็น "inline" ได้ ตอนนี้หน้าของเราจะแสดงข้อความ "สวัสดีนักเรียนที่มีการโต้ตอบ"

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

ตัวอย่างหน้าเว็บ

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

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

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

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

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

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

พูดง่ายๆ ก็คือ JavaScript นำเสนอทรัพยากร Dependency ใหม่ๆ มากมายระหว่างการทำงานของ 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 ในหน้า คุณคาดหวังให้ทั้งคู่ทำงานในลักษณะเดียวกัน ในทั้งสองกรณี เบราว์เซอร์จะหยุดและเรียกใช้สคริปต์ก่อนที่จะประมวลผลส่วนที่เหลือของเอกสารได้ อย่างไรก็ตาม ในกรณีของไฟล์ JavaScript ภายนอก เบราว์เซอร์จะต้องหยุดชั่วคราวเพื่อรอให้มีการดึงข้อมูลสคริปต์จากดิสก์ แคช หรือเซิร์ฟเวอร์ระยะไกล ซึ่งจะทำให้เกิดความล่าช้าหลายหมื่นมิลลิวินาทีสำหรับเส้นทางการแสดงผลวิกฤติ

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

เพื่อให้บรรลุเป้าหมายนี้ เราจะทำเครื่องหมายสคริปต์ว่าasync ดังนี้

<!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>

ลองใช้

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

ความคิดเห็น