นักพัฒนา Node.js เกือบทั้งหมดสามารถบอกคุณได้ว่าฟังก์ชั่น `ต้องการ ()` ทำอย่างไร แต่มีกี่คนที่รู้ว่ามันทำงานอย่างไร เราใช้มันทุกวันเพื่อโหลดห้องสมุดและโมดูล แต่พฤติกรรมของมันเป็นเรื่องลึกลับสำหรับเรา
ด้วยความอยากรู้อยากเห็นฉันเจาะลึกลงไปในรหัสหลักของโหนดเพื่อค้นหาว่าเกิดอะไรขึ้นภายใต้เครื่องยนต์ แต่นี่ไม่ใช่ฟังก์ชั่นเดียว ฉันพบ module.js ในระบบโมดูลโหนด ไฟล์มีโมดูลแกนหลักที่ทรงพลังและไม่คุ้นเคยอย่างน่าประหลาดใจซึ่งควบคุมการโหลดการรวบรวมและการแคชของแต่ละไฟล์ `ต้องการ ()` การเกิดขึ้นของมันเป็นเพียงส่วนปลายของภูเขาน้ำแข็ง
module.js
การคัดลอกรหัสมีดังนี้:
โมดูลฟังก์ชั่น (ID, PARTE) {
this.id = id;
this.exports = {};
this.parent = Parent;
-
ใน module.js ส่วนใหญ่เล่นสองบทบาทภายใน node.js ก่อนอื่นจะเป็นรากฐานสำหรับโมดูล Node.js ทั้งหมด แต่ละไฟล์เป็นอินสแตนซ์ใหม่ของโมดูลฐานใหม่และยังคงมีอยู่แม้หลังจากเรียกใช้ไฟล์แล้ว นี่คือเหตุผลที่เราสามารถแนบคุณสมบัติเข้ากับโมดูลส่งออกและส่งคืนเมื่อจำเป็น
ภารกิจสำคัญที่สองของโมดูลนี้คือการจัดการกลไกการโหลดโมดูลของโหนด การทำงานที่เป็นอิสระของฟังก์ชั่น "ต้องการ" ที่เราใช้นั้นเป็นโมดูลแนวคิดนามธรรม require ซึ่งเป็นเพียงการห่อหุ้มง่าย ๆ เกี่ยวกับโมดูลฟังก์ชัน _load วิธีการโหลดนี้จัดการการโหลดจริงของแต่ละไฟล์และเริ่มการเดินทางของเราที่นั่น
module._load
การคัดลอกรหัสมีดังนี้:
module._load = function (คำขอ, parent, ismain) {
// 1. ตรวจสอบโมดูล _cache สำหรับโมดูลแคช
// 2. สร้างอินสแตนซ์โมดูลใหม่หากแคชว่างเปล่า
// 3. บันทึกลงในแคช
// 4. call module.load () ด้วยชื่อไฟล์ที่กำหนดของคุณ
// นี่จะเรียกโมดูล compile () หลังจากอ่านเนื้อหาไฟล์
// 5. หากมีข้อผิดพลาดในการโหลด/แยกวิเคราะห์ไฟล์
// ลบโมดูลที่ไม่ดีออกจากแคช
// 6. return module.exports
-
module._load รับผิดชอบในการโหลดโมดูลใหม่และการจัดการแคชโมดูล แคชที่โหลดแต่ละโมดูลจะลดจำนวนการอ่านของไฟล์ซ้ำซ้อนและสามารถเพิ่มความเร็วแอปพลิเคชันของคุณได้อย่างมาก นอกจากนี้อินสแตนซ์โมดูลที่ใช้ร่วมกันช่วยให้โมดูลที่มีลักษณะของ Singleton ยังคงอยู่ในสถานะในโครงการ
หากโมดูลไม่มีอยู่ในแคชโมดูล _load จะสร้างโมดูลฐานใหม่สำหรับไฟล์ จากนั้นจะบอกให้โมดูลอ่านเนื้อหาของไฟล์ใหม่ก่อนที่จะส่งไปยังโมดูล _compile [1]
หากคุณสังเกตเห็นขั้นตอนที่ #6 ด้านบนคุณจะเห็นโมดูลนั้นส่งคืนกลับไปยังผู้ใช้ นี่คือเหตุผลว่าทำไมเมื่อคุณกำหนดการใช้งานส่วนต่อประสานสาธารณะคุณใช้การส่งออกและโมดูลส่งออกเนื่องจากโมดูล _load จะส่งคืนเนื้อหาที่ต้องการ ฉันประหลาดใจที่ไม่มีคุณสมบัติอีกต่อไป แต่มันจะดีกว่าถ้ามี
module._compile
การคัดลอกรหัสมีดังนี้:
module.prototype._compile = function (เนื้อหา, ชื่อไฟล์) {
// 1. สร้างสแตนด์อโลนต้องการฟังก์ชั่นที่เรียกโมดูล require
// 2. แนบวิธีการช่วยอื่น ๆ ที่ต้องการ
// 3. ห่อรหัส JS ในฟังก์ชั่นที่ให้ความต้องการของเรา
// โมดูล ฯลฯ ตัวแปรที่อยู่ในขอบเขตของโมดูล
// 4. เรียกใช้ฟังก์ชั่นนั้น
-
・ นี่คือที่ที่ปาฏิหาริย์ที่แท้จริงเกิดขึ้น ก่อนอื่นฟังก์ชั่นต้องการการปฏิบัติงานอิสระพิเศษถูกสร้างขึ้นสำหรับโมดูล นี่คือคุณสมบัติที่เราต้องการและคุ้นเคย ฟังก์ชั่นนั้นเป็นเพียงการห่อหุ้มในโมดูล require ซึ่งยังมีวิธีเสริมที่ไม่รู้จักซึ่งเป็นเรื่องง่ายสำหรับเราที่จะใช้:
・ ต้องการ (): โหลดโมดูลภายนอก
・ require.resolve (): แยกวิเคราะห์ชื่อโมดูลเป็นเส้นทางสัมบูรณ์
・ ต้องการ. เมน: โมดูลหลัก
・ ต้องการ. แคช: โมดูลแคชทั้งหมด
・ ・ ・ ・ ・ การขยาย: วิธีการรวบรวมที่สามารถใช้สำหรับแต่ละประเภทไฟล์ที่ถูกต้องตามส่วนขยายของมัน
เมื่อความต้องการพร้อมใช้งานซอร์สโค้ดที่โหลดทั้งหมดจะถูกห่อหุ้มในฟังก์ชั่นใหม่ทำให้สามารถยอมรับต้องการโมดูลการส่งออกและตัวแปรที่เปิดเผยอื่น ๆ ทั้งหมดเป็นพารามิเตอร์ นี่คือฟังก์ชั่นที่สร้างขึ้นเพื่อห่อหุ้มโมดูลเพื่อป้องกันความขัดแย้งกับสภาพแวดล้อม node.js
การคัดลอกรหัสมีดังนี้:
(ฟังก์ชั่น (การส่งออก, ต้องการ, โมดูล, __filename, __dirName) {
// รหัสของคุณฉีดที่นี่!
-
Module._compile วิธีการแบบซิงโครนัสดังนั้นการเรียกไปยังโมดูล _load สามารถรอได้จนกว่ารหัสจะสิ้นสุดและส่งคืนโมดูล exprts ไปยังผู้ใช้
สรุปแล้ว
ดังนั้นเราจึงเข้าใจรหัสทั้งหมดของความต้องการและมีความเข้าใจเบื้องต้นเกี่ยวกับวิธีการทำงาน
หากคุณทำไปตลอดทางคุณก็พร้อมสำหรับความลับสุดท้าย: ต้องการ ('โมดูล') สิ่งนี้ถูกต้องระบบโมดูลสามารถโหลดผ่านระบบโมดูล เริ่มต้น สิ่งนี้อาจฟังดูแปลก แต่ช่วยให้พื้นที่ผู้ใช้สามารถโต้ตอบกับระบบโหลดโมดูลโดยไม่ต้องเจาะลึกลงไปใน Core Node.js โมดูลยอดนิยมทั้งหมดถูกสร้างขึ้นเช่นนี้ [2]
หากคุณต้องการทราบข้อมูลเพิ่มเติมโปรดตรวจสอบซอร์สโค้ด Module.js ด้วยตัวคุณเอง ยังมีอีกหลายสิ่งที่จะเพียงพอสำหรับคุณที่จะปวดหัวสักพัก คนแรกสามารถบอกฉันได้ว่า node_module_contexts คืออะไร "และทำไมมันถึงเพิ่มสามารถรับคะแนนโบนัส :)
[1] วิธีโมดูล _compile ใช้เพื่อเรียกใช้ไฟล์ JavaScript เท่านั้น ไฟล์ JSON จะต้องถูกแยกวิเคราะห์ผ่าน json.parse () และส่งคืน
[2] อย่างไรก็ตามโมดูลทั้งสองถูกสร้างขึ้นบนวิธีโมดูลส่วนตัวเช่นโมดูล _ResolVelaOkuppaths และโมดูล. _FindPath คุณสามารถคิดว่ามันไม่ได้ดีไปกว่านี้มาก ...