โหลดโมดูลล่วงหน้า

Sérgio Gomes

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

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

<link rel="preload"> เป็นวิธีขอทรัพยากรอย่างชัดเจน ก่อนที่เบราว์เซอร์จะจำเป็นต้องใช้

<head>
  <link rel="preload" as="style" href="critical-styles.css">
  <link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>

การรองรับเบราว์เซอร์

  • Chrome: 50
  • ขอบ: ≤79
  • Firefox: 85
  • Safari: 11.1

แหล่งที่มา

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

<link rel="preload"> และส่วนหัว HTTP ที่เทียบเท่ากันจะให้คำประกาศที่เรียบง่ายและชัดเจน วิธีแจ้งให้เบราว์เซอร์ทราบเกี่ยวกับไฟล์สำคัญที่จำเป็นทันที เป็นส่วนหนึ่งของการนำทางปัจจุบัน เมื่อเบราว์เซอร์เห็นการโหลดล่วงหน้า การโหลดล่วงหน้า ดาวน์โหลดลำดับความสำคัญ สำหรับทรัพยากร เพื่อที่เมื่อถึงเวลาที่จำเป็นจริงๆ อยู่แล้วหรือบางส่วน อย่างไรก็ตาม ไม่สามารถใช้งานได้สำหรับโมดูล

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

สำหรับแท็ก <script> และ <link> คุณจะตั้งค่าโหมดข้อมูลเข้าสู่ระบบได้ด้วย crossorigin แต่ปรากฏว่า <script type="module"> ที่ไม่มี แอตทริบิวต์ crossorigin ระบุโหมดข้อมูลเข้าสู่ระบบของ omit ซึ่งไม่มีอยู่ สำหรับ <link rel="preload"> ซึ่งหมายความว่าคุณจะต้องทำดังนี้ เปลี่ยนแอตทริบิวต์ crossorigin ทั้งใน <script> และ <link> เป็น 1 ค่าอื่นๆ และคุณอาจ ไม่วิธีง่ายๆ ในการดำเนินการดังกล่าวหากคุณ การโหลดล่วงหน้าจะขึ้นอยู่กับโมดูลอื่นๆ

นอกจากนี้ การดึงข้อมูลไฟล์เป็นเพียงขั้นตอนแรกในการเรียกใช้โค้ดเท่านั้น ก่อนอื่น เบราว์เซอร์จะต้องแยกวิเคราะห์และคอมไพล์ โดยหลักการแล้ว ซึ่งควรจะเกิดขึ้นล่วงหน้าด้วย ดังนั้น เมื่อจำเป็นต้องใช้โมดูลนี้ โค้ดจะ ที่พร้อมทำงาน อย่างไรก็ตาม V8 (เครื่องมือ JavaScript ของ Chrome) จะแยกวิเคราะห์และคอมไพล์โมดูล แตกต่างจาก JavaScript อื่นๆ <link rel="preload"> ไม่ได้ เป็นวิธีการบ่งชี้ว่าไฟล์ที่กำลังโหลดเป็นโมดูล ดังนั้นทุกเบราว์เซอร์ คือการโหลดไฟล์และใส่ไว้ในแคช เมื่อโหลดสคริปต์โดยใช้ แท็ก <script type="module"> (หรือโหลดโดยโมดูลอื่น) เบราว์เซอร์แยกวิเคราะห์ และคอมไพล์โค้ดเป็นโมดูล JavaScript

กล่าวโดยสรุปคือ ใช่ การมีประเภท link เฉพาะสำหรับโมดูลการโหลดล่วงหน้าช่วยให้เรา เขียน HTML ง่ายๆ โดยไม่ต้องกังวลว่าเรากําลังใช้โหมดข้อมูลรับรองอะไรอยู่ ค่าเริ่มต้นจะใช้งานได้

<head>
  <link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">

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

การรองรับเบราว์เซอร์

  • Chrome: 66
  • ขอบ: ≤79
  • Firefox: 115
  • Safari: 17.

แหล่งที่มา

แล้วโมดูลต่างๆ ล่ะ ทรัพยากร Dependency หรือไม่

คำถามตลกๆ ที่ควรจะถาม จริงๆ แล้วมีบางกรณีที่บทความนี้ไม่ครอบคลุม นั่นก็คือการเกิดซ้ำ

ข้อกำหนดของ <link rel="modulepreload"> จริงๆ แล้ว อนุญาตให้เลือกโหลดได้ ไม่ใช่แค่ โมดูลที่ขอ รวมถึงแผนผัง Dependency ทั้งหมดด้วย เบราว์เซอร์ไม่จำเป็นต้อง ทำสิ่งนี้ แต่ทำได้

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

เบราว์เซอร์ที่เลือกโหลดทรัพยากร Dependency ล่วงหน้าแบบเกิดซ้ำควรมีการกรองข้อมูลที่ซ้ำกันออกที่มีประสิทธิภาพ สำหรับโมดูล ดังนั้นโดยทั่วไป แนวทางปฏิบัติที่ดีที่สุดคือการประกาศโมดูลและรายการเดี่ยว ของทรัพยากร Dependency ได้ และเชื่อมั่นว่าเบราว์เซอร์จะไม่ดึงข้อมูลโมดูลเดียวกันซ้ำ 2 ครั้ง

<head>
  <!-- dog.js imports dog-head.js, which in turn imports
       dog-head-mouth.js, which imports dog-head-mouth-tongue.js. -->
  <link rel="modulepreload" href="dog-head-mouth-tongue.mjs">
  <link rel="modulepreload" href="dog-head-mouth.mjs">
  <link rel="modulepreload" href="dog-head.mjs">
  <link rel="modulepreload" href="dog.mjs">
</head>

โมดูลการโหลดล่วงหน้าช่วยเพิ่มประสิทธิภาพไหม

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

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