เผยแพร่เมื่อวันที่ 23 พฤศจิกายน 2024
การพัฒนาแบบโมดูลมีข้อดีบางอย่างที่แท้จริงในแง่ของการแคชได้ ซึ่งจะช่วยให้คุณลดจำนวนไบต์ที่ต้องส่งให้ผู้ใช้ รายละเอียดที่ละเอียดยิ่งขึ้นของโค้ดยังช่วยในเรื่องประสิทธิภาพการโหลดด้วย โดยให้คุณจัดลําดับความสําคัญของโค้ดที่สําคัญในแอปพลิเคชันได้
อย่างไรก็ตาม โมดูลที่ขึ้นต่อกันจะทำให้เกิดปัญหาในการโหลด เนื่องจากเบราว์เซอร์ต้องรอให้โมดูลโหลดก่อนที่จะค้นหาว่าโมดูลนั้นขึ้นต่อกันกับอะไร วิธีหนึ่งในการแก้ปัญหานี้คือโหลดไฟล์ที่ต้องพึ่งพาไว้ล่วงหน้าเพื่อให้เบราว์เซอร์ทราบเกี่ยวกับไฟล์ทั้งหมดล่วงหน้าและสามารถทำให้การเชื่อมต่อทำงานอยู่ได้
<link rel="preload">
<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>
ซึ่งจะทำงานได้ดีกับทรัพยากร เช่น แบบอักษร ซึ่งมักจะซ่อนอยู่ภายในไฟล์ CSS และบางครั้งก็อยู่ลึกหลายระดับ ในกรณีดังกล่าว เบราว์เซอร์จะต้องรอการติดต่อหลายรอบก่อนที่จะพบว่าต้องดึงข้อมูลไฟล์แบบอักษรขนาดใหญ่ ทั้งๆ ที่อาจใช้ช่วงเวลาดังกล่าวเพื่อเริ่มการดาวน์โหลดและใช้ประโยชน์จากแบนด์วิดท์การเชื่อมต่อได้อย่างเต็มที่
<link rel="preload">
และรูปแบบเทียบเท่าสำหรับ HTTP เป็นวิธีที่ง่ายและชัดเจนในการแจ้งให้เบราว์เซอร์ทราบทันทีเกี่ยวกับไฟล์ที่สำคัญซึ่งต้องใช้เป็นส่วนหนึ่งของการนําทางปัจจุบัน เมื่อเบราว์เซอร์เห็นการโหลดล่วงหน้า ก็จะเริ่มการดาวน์โหลดทรัพยากรที่มีลําดับความสําคัญสูง เพื่อให้โหลดทรัพยากรไว้ล่วงหน้าหรือบางส่วนไว้แล้วเมื่อถึงเวลาที่จําเป็น แต่จะใช้กับข้อบังคับไม่ได้
เหตุใด <link rel="preload">
จึงใช้กับข้อบังคับไม่ได้
ตรงนี้แหละที่เริ่มยุ่งยาก ข้อมูลเข้าสู่ระบบมีโหมดหลายโหมดสําหรับทรัพยากร และข้อมูลเข้าสู่ระบบต้องตรงกันจึงจะได้รับการตีกลับจากแคช ไม่เช่นนั้นระบบจะดึงข้อมูลทรัพยากร 2 ครั้ง ไม่ต้องสงสัยเลยว่าการดึงข้อมูลซ้ำนั้นไม่ดี เนื่องจากจะสิ้นเปลืองแบนด์วิดท์ของผู้ใช้และทำให้ผู้ใช้ต้องรอนานขึ้นโดยไม่มีเหตุผลอันควร
สําหรับแท็ก <script>
และ <link>
คุณสามารถตั้งค่าโหมดข้อมูลเข้าสู่ระบบด้วยแอตทริบิวต์ crossorigin
แต่ปรากฏว่า <script type="module">
ที่ไม่มีแอตทริบิวต์ crossorigin
บ่งบอกถึงโหมดข้อมูลเข้าสู่ระบบของ omit
ซึ่งไม่มีอยู่สำหรับ <link rel="preload">
ซึ่งหมายความว่าคุณจะต้องเปลี่ยนแอตทริบิวต์ crossorigin
ทั้งใน <script>
และ <link>
เป็นค่าอื่น และคุณอาจเปลี่ยนแอตทริบิวต์ดังกล่าวได้ยากหากสิ่งที่พยายามจะโหลดล่วงหน้าเป็นโมดูลที่ต้องพึ่งพาโมดูลอื่นๆ
นอกจากนี้ การดึงข้อมูลไฟล์เป็นเพียงขั้นตอนแรกในการเรียกใช้โค้ดจริง
ก่อนอื่นเบราว์เซอร์ต้องแยกวิเคราะห์และคอมไพล์ โดยควรดำเนินการล่วงหน้าด้วย เพื่อที่ว่าเมื่อต้องการใช้โมดูล โค้ดจะพร้อมใช้งาน อย่างไรก็ตาม V8 (เครื่องมือ JavaScript ของ Chrome) จะแยกวิเคราะห์และคอมไพล์โมดูลแตกต่างจาก JavaScript อื่นๆ <link rel="preload">
ไม่ได้ระบุวิธีใดๆ ที่บ่งบอกว่าไฟล์ที่โหลดเป็นโมดูล ดังนั้นเบราว์เซอร์จะทำได้เพียงโหลดไฟล์และใส่ไว้ในแคช เมื่อโหลดสคริปต์โดยใช้แท็ก <script type="module">
(หรือโหลดโดยโมดูลอื่น) แล้ว เบราว์เซอร์จะแยกวิเคราะห์และคอมไพล์โค้ดเป็นโมดูล JavaScript
<link rel="modulepreload">
จะใช้ได้กับข้อบังคับเท่านั้นใช่ไหม<link rel="preload">
สรุปสั้นๆ คือ ใช่ การมี link
ประเภทที่เฉพาะเจาะจงสำหรับการโหลดโมดูลล่วงหน้าช่วยให้เราเขียน HTML ง่ายๆ ได้โดยไม่ต้องกังวลว่าจะใช้โหมดข้อมูลเข้าสู่ระบบใด ค่าเริ่มต้นใช้งานได้เลย
<head>
<link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">
และเนื่องจากตอนนี้เบราว์เซอร์ทราบว่าสิ่งที่คุณกำลังโหลดล่วงหน้าคือโมดูล เบราว์เซอร์จึงสามารถทํางานอย่างชาญฉลาด โดยแยกวิเคราะห์และคอมไพล์โมดูลทันทีที่ดึงข้อมูลเสร็จสิ้น แทนที่จะรอจนกว่าระบบจะพยายามเรียกใช้
แล้วทรัพยากร Dependency ของโมดูลล่ะ
คำถามนี้ดีมาก บทความนี้ไม่ได้กล่าวถึงเรื่องหนึ่งที่สำคัญมาก นั่นก็คือ การเกิดซ้ำ
ข้อกำหนด <link rel="modulepreload">
อนุญาตให้โหลดไม่เพียงโมดูลที่ขอเท่านั้น แต่ยังโหลดทั้งลําดับชั้นของข้อกําหนดที่เกี่ยวข้องทั้งหมดด้วย เบราว์เซอร์ไม่จำเป็นต้องดำเนินการนี้ แต่สามารถดำเนินการได้
โซลูชันข้ามเบราว์เซอร์ที่ดีที่สุดสำหรับการโหลดโมดูลและต้นไม้ความเกี่ยวข้องล่วงหน้าคืออะไร เนื่องจากคุณต้องใช้ต้นไม้ความเกี่ยวข้องทั้งหมดเพื่อเรียกใช้แอป
เบราว์เซอร์ที่เลือกโหลดพึ่งพาล่วงหน้าแบบซ้ำซ้อนควรมีการกรองข้อมูลที่ซ้ำกันออกอย่างมีประสิทธิภาพสำหรับโมดูล ดังนั้นโดยทั่วไปแล้วแนวทางปฏิบัติแนะนำคือการประกาศโมดูลและรายการแบบแบนสำหรับพึ่งพาของโมดูลนั้น และไว้วางใจให้เบราว์เซอร์ไม่ดึงข้อมูลโมดูลเดียวกันซ้ำ
<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 เราจึงใกล้จะถึงเวลาให้นักจัดกลุ่มได้พักผ่อนอย่างสมเหตุสมผลแล้ว