الفرق بين المراجعتين لصفحة: «Node.js/modules»

من موسوعة حسوب
لا ملخص تعديل
ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}'
 
(8 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
الوحدات (Modules)
<noinclude>{{DISPLAYTITLE: الوحدات (Modules) في Node.js}}</noinclude>
 
مؤشر الاستقرار: 2 - مستقر
مؤشر الاستقرار: 2 - مستقر


سطر 51: سطر 50:


== Addenda: نصائح عن مدير الحِزم ==
== Addenda: نصائح عن مدير الحِزم ==
صُممت دلالات الدالة require()‎ في Node.js لتكون عامة بما يكفي لدعم عدد من هياكل المجلدات المعقولة. تأمل تطبيقات إدارة حِزم البرامج مثل dpkg و rpm و npm، تجد أنه من الممكن بناء حزم أصلية من وحدات Node.js دون تعديل.
صُممت دلالات الدالة <code>require()‎</code> في Node.js لتكون عامة بما يكفي لدعم عدد من هياكل المجلدات المعقولة. تأمل تطبيقات إدارة حِزم البرامج مثل <code>dpkg</code> و <code>rpm</code> و <code>npm</code>، تجد أنه من الممكن بناء حزم أصلية من وحدات Node.js دون تعديل.
 
فيما يلي مُقترح بنية مُجلد والتي يمكن أن تعمل:
فيما يلي مُقترح بنية مُجلد والتي يمكن أن تعمل:
لنفرض أننا نريد أن يحتوي المجلد /usr/lib/node/<some-package>/<some-version> على محتويات إصدار محدد لحزمةٍ ما.
 
يمكن أن تعتمد الحزم على بعضها البعض. فمن أجل تثبيت حزمة foo، قد يلزم تثبيت إصدار محدد من حزمة bar. وقد يكون لحزمة bar نفسها ‫اعتماديات، وفي بعض الحالات، قد تتعارض أو تشكل اعتماديات دورية.
لنفرض أننا نريد أن يحتوي المجلد ‎<code>/usr/lib/node/<some-package>/<some-version>‎</code> على محتويات إصدار محدد لحزمةٍ ما.
ولما كانت Node.js تبحث عن المسار الحقيقي realpath للوحدات التي تُحمِّلها (أي، يحل الوصلات الرمزية)، ومن ثَمَّ يبحث عن اعتمادياتها في مجلدات node_modules، ويُعد هذا الوضع بسيط جداً للحل مع البنية التالية:
 
    • /‎/usr/lib/node/foo/1.2.3/‎‎‎  - محتويات حزمة foo، الإصدار 1.2.3.
يمكن أن تعتمد الحزم على بعضها البعض. فمن أجل تثبيت الحزمة <code>foo</code>، قد يلزم تثبيت إصدار محدد من الحزمة <code>bar</code>. وقد يكون للحزمة <code>bar</code> نفسها ‫اعتماديات، وفي بعض الحالات، قد تتعارض أو تشكل اعتماديات دورية.
    • /‎/usr/lib/node/bar/4.3.2/‎‎  - محتويات حزمة bar التي تعتمد عليها حزمة foo.
 
    • /‎/‎usr/lib/node/foo/1.2.3/node_modules/bar - وصلة رمزية تشير إلى /usr/lib/node/bar/4.3.2/.
ولما كانت Node.js تبحث عن المسار الحقيقي <code>realpath</code> للوحدات التي تُحمِّلها (أي، تستبين الوصلات الرمزية)، ومن ثَمَّ يبحث عن اعتمادياتها في مجلدات <code>node_modules</code>، ويُعد هذا الوضع بسيط جدًا للحل مع البنية التالية:
    • /‎/‎usr/lib/node/bar/4.3.2/node_modules/‎*‎ وصلة رمزية تشير إلى الحزمة التي تعتمد عليها الحزمة bar.
* <code>/usr/lib/node/foo/1.2.3/‎‎‎</code>: محتويات حزمة <code>foo</code>، الإصدار 1.2.3.
* <code>/usr/lib/node/bar/4.3.2/‎‎</code>: محتويات حزمة <code>bar</code> التي تعتمد عليها حزمة <code>foo</code>.
* <code>/‎/‎usr/lib/node/foo/1.2.3/node_modules/bar</code>: وصلة رمزية تشير إلى <code>/usr/lib/node/bar/4.3.2/</code>.
* <code>/‎‎usr/lib/node/bar/4.3.2/node_modules/‎*‎</code>: وصلة رمزية تشير إلى الحزمة التي تعتمد عليها الحزمة <code>bar</code>.
وهكذا، حتى إذا صودفت دورة، أو إذا كان هناك تعارضات في الاعتمادية، ستكون كل وحدة قادرةً على الحصول على نسخة الاعتمادية التي يمكن أن تستخدمها.
وهكذا، حتى إذا صودفت دورة، أو إذا كان هناك تعارضات في الاعتمادية، ستكون كل وحدة قادرةً على الحصول على نسخة الاعتمادية التي يمكن أن تستخدمها.
عندما تحتاج التعليمات البرمجية في حزمة  foo إلى استدعاء require('bar')، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية ‎/usr/lib/node/foo/1.2.3/node_modules/bar. كذلك، عندما تحتاج التعليمات البرمجية في حزمة  bar إلى استدعاءrequire('quux')، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية  ‎/usr/lib/node/bar/4.3.2/node_modules/quux.
وعلاوة على ذلك, لجعل عملية البحث في الوحدة أحسن أداءً، يمكن وضع الحزم في‎/usr/lib/node_modules/<name>/<version>‎ بدلا من وضعها مباشرة في ‎/usr/lib/node. لا تهتم Node.js بالبحث عن الاعتماديات المفقودة في ‎/usr/node_modules أو ‎/node_modules.
لإتاحة الوحدات لـ Node.js REPL، قد يكون من المفيد أيضا إضافة المجلد ‎/usr/lib/node_modules إلى متغير البيئة ‎$NODE_PATH. ولما كان البحث في الوحدات باستخدام المجلدات node_modules نسبيًا، واستنادا إلى المسار الحقيقي لملفات استدعاء require()‎، يمكن أن تكون الحزم نفسها في أي مكان.
All Together...
تُستخدم الدالة require.resolve()‎ للحصول على اسم الملف الصحيح الذي سيُحمَّل عند استدعاء require()‎.
بتجميع كل ما سبق، فيما يلي خوارزمية رفيعة المستوى في شكل شيفرة وهمية (pseudocode) عما يجريه require.resolve()‎:


التخزين المؤقت (Caching)
عندما تحتاج التعليمات البرمجية في حزمة <code>foo</code> إلى استدعاء <code>require('bar')</code>‎، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية <code>‎/usr/lib/node/foo/1.2.3/node_modules/bar</code>. كذلك، عندما تحتاج التعليمات البرمجية في حزمة <code>bar</code> إلى استدعاء <code>require('quux')‎</code>، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية <code>‎/usr/lib/node/bar/4.3.2/node_modules/quux</code>.
تُخزَّن الوحدات مؤقتًا بعد تحميلها أول مرة. وهذا يعني (من ضمن أمور أخرى) أن كل استدعاء للتابع require('foo') سوف يعيد بالضبط الكائن نفسه إذ كان يحل نفس الملف.
 
قد لا تسبب عدة استدعاءات للتابع require('foo') تنفيذ شيفرة الوحدة عدة مرات. وهي ميزة هامة. مع ذلك، يمكن إعادة الكائنات "المُنفَّذة جزئيًا"، مما يسمح بتحميل الاعتماديات الانتقالية حتى عندما تتسبب في دورات.
وعلاوة على ذلك, لجعل عملية البحث في الوحدة أحسن أداءً، يمكن وضع الحزم في‎<code>/usr/lib/node_modules/<name>/<version></code>‎ بدلًا من وضعها مباشرة في <code>‎/usr/lib/node</code>. لا تهتم Node.js بالبحث عن الاعتماديات المفقودة في ‎<code>/usr/node_modules</code> أو <code>‎/node_modules</code>.
 
لإتاحة الوحدات لـ Node.js REPL، قد يكون من المفيد أيضًا إضافة المجلد <code>‎/usr/lib/node_modules</code> إلى متغير البيئة <code>‎$NODE_PATH</code>. ولما كان البحث في الوحدات باستخدام المجلدات <code>node_modules</code> نسبيًا، واستنادا إلى المسار الحقيقي لملفات استدعاء <code>require()‎</code>، يمكن أن تكون الحزم نفسها في أي مكان.
 
== خلاصة الكلام السابق ==
تُستخدم الدالة <code>require.resolve()‎</code> للحصول على اسم الملف الصحيح الذي سيُحمَّل عند استدعاء <code>require()‎</code>.
 
بتجميع كل ما سبق، فيما يلي خوارزمية رفيعة المستوى في شكل شيفرة وهمية (pseudocode) عما يجريه <code>require.resolve()‎</code>:<syntaxhighlight lang="javascript">
require(X) from module at path Y
1. If X is a core module,
  a. return the core module
  b. STOP
2. If X begins with '/'
  a. set Y to be the filesystem root
3. If X begins with './' or '/' or '../'
  a. LOAD_AS_FILE(Y + X)
  b. LOAD_AS_DIRECTORY(Y + X)
4. LOAD_NODE_MODULES(X, dirname(Y))
5. THROW "not found"
 
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.json is a file, parse X.json to a JavaScript Object.  STOP
4. If X.node is a file, load X.node as binary addon.  STOP
 
LOAD_INDEX(X)
1. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon.  STOP
 
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
  a. Parse X/package.json, and look for "main" field.
  b. let M = X + (json main field)
  c. LOAD_AS_FILE(M)
  d. LOAD_INDEX(M)
2. LOAD_INDEX(X)
 
LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
  a. LOAD_AS_FILE(DIR/X)
  b. LOAD_AS_DIRECTORY(DIR/X)
 
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = [GLOBAL_FOLDERS]
4. while I >= 0,
  a. if PARTS[I] = "node_modules" CONTINUE
  b. DIR = path join(PARTS[0 .. I] + "node_modules")
  c. DIRS = DIRS + DIR
  d. let I = I - 1
5. return DIRS
 
</syntaxhighlight>
 
== التخزين المؤقت (Caching) ==
تُخزَّن الوحدات مؤقتًا بعد تحميلها أول مرة. وهذا يعني (من ضمن أمور أخرى) أن كل استدعاء للتابع <code>require('foo')‎</code> سوف يعيد بالضبط الكائن نفسه إذ كان يحل نفس الملف.
 
قد لا تسبب عدة استدعاءات للتابع <code>require('foo')‎</code> تنفيذ شيفرة الوحدة عدة مرات. وهي ميزة هامة. مع ذلك، يمكن إعادة الكائنات "المُنفَّذة جزئيًا"، مما يسمح بتحميل الاعتماديات الانتقالية حتى عندما تتسبب في دورات.
 
لتنفيذ التعليمات البرمجية لوحدة عدة مرات يجب تصدير دالة واستدعاء هذه الدالة.
لتنفيذ التعليمات البرمجية لوحدة عدة مرات يجب تصدير دالة واستدعاء هذه الدالة.
محاذير التخزين المؤقت للوحدات
 
تُخزين الوحدات مؤقتاً على أساس حل اسم الملف. لما كان حل الوحدات إلى اسم ملف مختلف على أساس موقع الوحدة المُستدعِية (تحميل من مجلدات node_modules)، فإنه لا يضمن أن يُعيد التابع require('foo') دائماً نفس الكائن بالضبط، إذا كان يحل لملفات مختلفة.
=== محاذير التخزين المؤقت للوحدات ===
بالإضافة إلى ذلك، في أنظمة الملفات أو أنظمة التشغيل الحساسة لحالة الأحرف، يمكن أن تشير الأسماء المحلولة المختلفة إلى نفس الملف، ولكن ذاكرة التخزين المؤقت ستستمر في التعامل معها كوحدات مختلفة، وستُحمل الملف عدة مرات. على سبيل المثال، يعيد كلٌ من require('./foo') و require('./FOO') كائنين مختلفين، بغض النظر عن ما إذا كان  ‎./foo و ‎./FOO هما نفس الملف.
تُخزين الوحدات مؤقتاً على أساس حل اسم الملف. لما كان حل الوحدات إلى اسم ملف مختلف على أساس موقع الوحدة المُستدعِية (تحميل من مجلدات <code>node_modules</code>)، فإنه لا يضمن أن يُعيد التابع <code>require('foo')‎</code> دائمًا نفس الكائن بالضبط، إذا كان يحل لملفات مختلفة.
الوحدات الأساسية
 
بالإضافة إلى ذلك، في أنظمة الملفات أو أنظمة التشغيل الحساسة لحالة الأحرف، يمكن أن تشير الأسماء المحلولة المختلفة إلى نفس الملف، ولكن ذاكرة التخزين المؤقت ستستمر في التعامل معها كوحدات مختلفة، وستُحمل الملف عدة مرات. على سبيل المثال، يعيد كلٌ من <code>require('./foo')‎</code> و <code>require('./FOO')‎</code> كائنين مختلفين، بغض النظر عن ما إذا كان  ‎<code>./foo</code> و <code>‎./FOO</code> هما نفس الملف.
 
== الوحدات الأساسية ==
تتمتع بيئة Node.js بالعديد من الوحدات المترجمة إلى النظام الثنائي. وتوصف هذه الوحدات بمزيد من التفصيل في مكان آخر من هذا التوثيق.
تتمتع بيئة Node.js بالعديد من الوحدات المترجمة إلى النظام الثنائي. وتوصف هذه الوحدات بمزيد من التفصيل في مكان آخر من هذا التوثيق.
وتُعرَّف الوحدات الأساسية داخل مصدر Node.js وهي موجودة في المجلد  lib/.
 
وتُحمَّل الوحدات الأساسية دائماً بشكل تفضيلي إذا مُرر المعرف الخاص بها إلى require()‎. على سبيل المثال، يعيد require('http') دائماً وحدة HTTP المُضمَّنة، حتى إذا كان هناك ملف بهذا الاسم.
وتُعرَّف الوحدات الأساسية داخل مصدر Node.js وهي موجودة في المجلد <code>lib/‎</code>.
الدورات
 
عندما تكون هناك استدعاءات require()‎ دائرية، قد لا تنتهي الوحدة من التنفيذ عند إعادتها.
وتُحمَّل الوحدات الأساسية دائمًا بشكل تفضيلي إذا مُرر المعرف الخاص بها إلى <code>require()</code>‎. على سبيل المثال، يعيد <code>require('http')‎</code> دائماً وحدة HTTP المُضمَّنة، حتى إذا كان هناك ملف بهذا الاسم.
 
== الدورات ==
عندما تكون هناك استدعاءات <code>require()</code>‎ دائرية، قد لا تنتهي الوحدة من التنفيذ عند إعادتها.
 
إليك هذه الحالة:
إليك هذه الحالة:
a.js:


b.js:
<code>a.js</code>:<syntaxhighlight lang="javascript">
console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');
 
</syntaxhighlight><code>b.js</code>:<syntaxhighlight lang="javascript">
console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
 
</syntaxhighlight><code>main.js</code>:<syntaxhighlight lang="javascript">
console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);


main.js:
</syntaxhighlight>عند تحميل <code>main.js</code> للوحدة <code>a.js</code>، ثم تحمِّل <code>a.js</code> بدورها الوحدةَ <code>b.js</code>. عند هذه النقطة، تحاول <code>b.js</code> لتحميل <code>a.js</code>. من أجل منع حلقة لا نهائية، تُعاد نسخة غير مكتملة لكائن <code>exports</code> الخاص بالوحدة <code>a.js</code> إلى الوحدة <code>b.js</code>. ثم تنهي الوحدة <code>b.js</code> التحميل، وتُعيد كائن <code>exports</code> إلى الوحدة <code>a.js</code>.


عند تحميل main.js للوحدة a.js، ثم تحمِّل a.js بدورها الوحدةَ b.js. عند هذه النقطة، تحاول b.js لتحميل a.js. من أجل منع حلقة لا نهائية، تُعاد نسخة غير مكتملة لكائن exports الخاص بالوحدة a.js إلى الوحدة b.js. ثم تنهي الوحدة b.js التحميل، وتُعيد كائن exports إلى الوحدة a.js.
عند تحميل <code>main.js</code> لكلتا الوحدتين، تنتهي كل منهما. سيكون الناتج من هذا البرنامج بالتالي هو:<syntaxhighlight lang="javascript">
عند تحميل main.js لكلتا الوحدتين، تنتهي كل منهما. سيكون الناتج من هذا البرنامج بالتالي هو:
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true


التخطيط الدقيق مطلوب للسماح لاعتماديات الوحدات النمطية كي تعمل بشكل صحيح داخل أي تطبيق.
</syntaxhighlight>التخطيط الدقيق مطلوب للسماح لاعتماديات الوحدات النمطية كي تعمل بشكل صحيح داخل أي تطبيق.
وحدات الملفات
إذا لم يُعثر على اسم الملف الصحيح، ستحاول Node.js تحميل اسم الملف المطلوب مع امتدادات إضافية: ‎.js و ‎.json، وأخيراً ‎.node.
تُفسر ملفات ‎.js على أنها ملفات JavaScript نصية، وثُحلَّل الملفات ‎.json كملفات JSON نصية.  وتُفسَّر ملفات ‎.node كوحدات مُترجَمة مُلحَقة ومُحمَّلة مع dlopen.
الوحدة المُستدعاة المسبوقة بالعلامة '/' تمثل المسار المطلق للملف. على سبيل المثال، سيُحمِّل require('/home/marco/foo.js') الملف ‎/home/marco/foo.js.
تمثل الوحدة المُستدعاة المسبوقة بالعلامة '/.' المسار النسبي للملف المُستدعي require()‎. فيجب أن يكون circle.js في نفس المجلد مع foo.js حتى يتمكن require('./circle') من العثور عليه.
بدون البادئة '/' أو ‎‎'‎./'‎ أو ‎'../'‎ للإشارة إلى ملف، يجب أن تكون الوحدة وحدةً أساسيةً أو أن تكون مُحملة من مجلد node_modules.
إذا كان المسار غير موجود، سوف يلقي require()‎ الخطأ Error مع رمز الخاصية code بالقيمة 'MODULE_NOT_FOUND'.
المجلدات كوحدات
من الملائم تنظيم البرامج والمكتبات في مجلدات متضمنة ذاتيًا، ومن ثَمَّ توفير نقطة دخول واحدة إلى المكتبة. هناك ثلاث طرق لتمرير مجلد إلى require()‎ كوسيط.
الأولى عن طريق إنشاء ملف package.json في جذر المجلد، الذي يحدد وحدة رئيسية main. مثال لملف package.json قد يبدو كما يلي:


إذا كان هذا في مجلد ‎./some-library، ثم محاولة require('./some-library') لتحميل ‎./some-library/lib/some-library.js.
== وحدات الملفات ==
هذا هو مدى تمييز Node.js لملفات package.json.
إذا لم يُعثر على اسم الملف الصحيح، ستحاول Node.js تحميل اسم الملف المطلوب مع امتدادات إضافية: <code>‎.js</code> و <code>‎.json</code>، وأخيراً <code>‎.node</code>.
إذا كان الملف المحدد بواسطة المُدخَل الرئيسي 'main' هو package.json مفقود ولا يمكن أن يُحل، سيُبلِغ Node.js أن الوحدة كاملةً مفقودة بسبب الخطأ الافتراضي:
 
تُفسر ملفات <code>‎.js</code> على أنها ملفات JavaScript نصية، وثُحلَّل الملفات <code>‎.json</code> كملفات JSON نصية.  وتُفسَّر ملفات <code>‎.node</code> كوحدات مُترجَمة مُلحَقة ومُحمَّلة مع <code>dlopen</code>.
 
الوحدة المُستدعاة المسبوقة بالعلامة '<code>/</code>' تمثل المسار المطلق للملف. على سبيل المثال، سيُحمِّل <code>require('/home/marco/foo.js')‎</code> الملف <code>‎/home/marco/foo.js</code>.
 
تمثل الوحدة المُستدعاة المسبوقة بالعلامة '<code>/.</code>' المسار النسبي للملف المُستدعي <code>require()</code>‎. فيجب أن يكون <code>circle.js</code> في نفس المجلد مع <code>foo.js</code> حتى يتمكن <code>require('./circle')‎</code> من العثور عليه.
 
بدون البادئة '<code>/</code>' أو ‎‎'‎<code>./</code>'‎ أو ‎'<code>../</code>'‎ للإشارة إلى ملف، يجب أن تكون الوحدة وحدةً أساسيةً أو أن تكون مُحملة من مجلد <code>node_modules</code>.
 
إذا كان المسار غير موجود، سوف يلقي <code>require()‎</code> الخطأ <code>Error</code> مع رمز الخاصية <code>code</code> بالقيمة '<code>MODULE_NOT_FOUND</code>'.
 
== المجلدات كوحدات ==
من الملائم تنظيم البرامج والمكتبات في مجلدات متضمنة ذاتيًا، ومن ثَمَّ توفير نقطة دخول واحدة إلى المكتبة. هناك ثلاث طرق لتمرير مجلد إلى <code>require()‎</code> كوسيط.
 
الأولى عن طريق إنشاء ملف <code>package.json</code> في جذر المجلد، الذي يحدد وحدة رئيسية <code>main</code>. مثال لملف <code>package.json</code> قد يبدو كما يلي:<syntaxhighlight lang="javascript">
{ "name" : "some-library",
  "main" : "./lib/some-library.js" }
 
</syntaxhighlight>إذا كان هذا في مجلد <code>‎./some-library</code>، فسيحاول التعبير <code>require('./some-library')‎</code> تحميل <code>‎./some-library/lib/some-library.js</code>.
 
هذا هو مدى تمييز Node.js لملفات <code>package.json</code>.
 
إذا كان الملف المحدد بواسطة المُدخَل الرئيسي '<code>main</code>' هو <code>package.json</code> مفقود ولا يمكن أن يُستبين، سيُبلِغ Node.js أن الوحدة كاملةً مفقودة بسبب الخطأ الافتراضي:<syntaxhighlight lang="javascript">
Error: Cannot find module 'some-library'‎
Error: Cannot find module 'some-library'‎
إذا لم يكن هناك أي ملف package.json موجودًا في المجلد، ستحاول Node.js تحميل ملف index.js أو index.node من داخل هذا المجلد. على سبيل المثال، إذا لم يكن هناك أي ملف package.json في المثال أعلاه، سيحاول require('./some-library') عندئذ تحميل:
</syntaxhighlight>إذا لم يكن هناك أي ملف <code>package.json</code> موجودًا في المجلد، ستحاول Node.js تحميل ملف <code>index.js</code> أو <code>index.node</code> من داخل هذا المجلد. على سبيل المثال، إذا لم يكن هناك أي ملف <code>package.json</code> في المثال أعلاه، سيحاول <code>require('./some-library')‎</code> عندئذ تحميل:
    • .‎./some-library/index.js
* <code>‎./some-library/index.js</code>
    • .‎./some-library/index.node
* <code>‎./some-library/index.node</code>
تحميل من مجلدات node_modules  
 
إذا كان مُعرِّف الوحدة المُمررة إلى require()‎ ليس وحدة نواة core، ولا يبدأ مع  '/' أو '‎../'‎ أو '‎./‎'، ثم تبدأ Node.js من المجلد الأصل للوحدة الحالية، ويضيف ‎/node_modules، ويحاول تحميل الوحدة من ذلك الموقع. لن تلحق Node المجلد node_modules إلى مسار منتهي بالفعل بالمجلد node_modules.
== التحميل من مجلدات <code>node_modules</code> ==
إذا لم يكن موجوداً، ينتقل إلى المجلد الأصل، وهلم جرا، حتى يصل إلى جذر نظام الملفات.
إذا كان مُعرِّف الوحدة المُمررة إلى <code>require()‎</code> ليس وحدة نواة <code>core</code>، ولا يبدأ مع '<code>/</code>' أو <code>‎../</code>'‎' أو '<code>‎./‎</code>'، ثم تبدأ Node.js من المجلد الأصل للوحدة الحالية، وتضيف <code>‎/node_modules</code>، وتحاول تحميل الوحدة من ذلك الموقع. لن تلحق Node المجلد <code>node_modules</code> إلى مسار منتهي بالفعل بالسلسلة النصية <code>node_modules</code>.
على سبيل المثال، إذا كان الملف في ‎'/home/ry/projects/foo.js'‎ يستدعي require('bar.js')، سوف يبحث Node.js في المواقع التالية بهذا الترتيب:‎
إذا لم يكن موجودًا، ينتقل إلى المجلد الأصل، وهلم جرًا، حتى يصل إلى جذر نظام الملفات.
‎‎
 
/home/ry/projects/node_modules/bar.js‎
على سبيل المثال، إذا كان الملف في ‎'<code>/home/ry/projects/foo.js</code>'‎ يستدعي <code>require('bar.js')‎</code>، فسوف تبحث Node.js في المواقع التالية بهذا الترتيب:
‎/home/ry/node_modules/bar.js
* <code>/home/ry/projects/node_modules/bar.js</code>
‎/home/node_modules/bar.js
* <code>/home/ry/node_modules/bar.js</code>
‎/node_modules/bar.js
* <code>/home/node_modules/bar.js</code>
* <code>/node_modules/bar.js</code>
وهذا يسمح للبرامج بتحديد مواقع اعتمادياتها بحيث لا تتصادم.
وهذا يسمح للبرامج بتحديد مواقع اعتمادياتها بحيث لا تتصادم.
فمن الممكن طلب ملفات محددة أو وحدات فرعية موزعة مع وحدة عن طريق تضمين مسار لاحق بعد اسم الوحدة. فعلى سبيل المثال سيحل require('example-module/path/to/file') إلى الملف path/to/file بالنسبة إلى حيث يوجد example-module. ويتبع المسار الملحق نفس دلالات حل الوحدات.
فمن الممكن طلب ملفات محددة أو وحدات فرعية موزعة مع وحدة عن طريق تضمين مسار لاحق بعد اسم الوحدة. فعلى سبيل المثال سيحل <code>require('example-module/path/to/file')‎</code> إلى الملف <code>path/to/file</code> بالنسبة إلى حيث يوجد <code>example-module</code>. ويتبع المسار الملحق نفس دلالات حل الوحدات.
تحميل من المجلدات العامة  
 
إذا ضُبط متغير البيئة NODE_PATH على قائمة مسارات مطلقة محددة بنقطتين رأسيتين ':'، سيبحث Node.js في تلك المسارات عن وحدات إذا لم تكن موجودة في أماكن أخرى.
== التحميل من المجلدات العامة ==
في Windows، يُحدد NODE_PATH بواسطة فاصلة منقوطة ';' بدلاً من النقطتين الرأسيتين ':'.
إذا ضُبط متغير البيئة <code>NODE_PATH</code> على قائمة مسارات مطلقة محددة بنقطتين رأسيتين '<code>:</code>ستبحث Node.js في تلك المسارات عن وحدات إذا لم تكن موجودة في أماكن أخرى.
أُنشئت NODE_PATH أصلاً لدعم تحميل الوحدات من مسارات مختلفة قبل تجميد خوارزمية حل الوحدة الحالية.
في ويندوز، يُحدد <code>NODE_PATH</code> بواسطة فاصلة منقوطة '<code>;</code>' بدلاً من النقطتين الرأسيتين ':'.
لا تزال NODE_PATH مدعومة، ولكن ليس من الضروري أن يستقر نظام Node.js الإيكولوجي على تقليدٍ ما لتحديد أماكن الوحدات التابعة. في بعض الأحيان تُظهر عمليات النشر التي تعتمد على NODE_PATH سلوكًا غريبًا عند عدم تعيين NODE_PATH. في بعض الأحيان تغيير اعتماديات الوحدة، مما يتسبب في تحميل إصدار مختلف (أو حتى وحدة مختلفة) أثناء البحث في NODE_PATH.
 
بالإضافة إلى ذلك، ستبحث Node.js في القائمة التالية من GLOBAL_FOLDERS:
أُنشئت <code>NODE_PATH</code> أصلاً لدعم تحميل الوحدات من مسارات مختلفة قبل تجميد خوارزمية حل الوحدة الحالية.
    •
 
حيث ‎$HOME هو المجلد الرئيسي للمستخدم، و ‎$PREFIX هو بادئة node_prefix المُكوّنة لبيئة Node.js.
ما تزال <code>NODE_PATH</code> مدعومة، ولكن ليس من الضروري أن يستقر نظام Node.js الإيكولوجي على تقليدٍ ما لتحديد أماكن الوحدات التابعة. في بعض الأحيان تُظهر عمليات النشر التي تعتمد على <code>NODE_PATH</code> سلوكًا غريبًا عند عدم تعيين <code>NODE_PATH</code>. في بعض الأحيان تغيير اعتماديات الوحدة، مما يتسبب في تحميل إصدار مختلف (أو حتى وحدة مختلفة) أثناء البحث في <code>NODE_PATH</code>.
 
بالإضافة إلى ذلك، ستبحث Node.js في القائمة التالية من <code>GLOBAL_FOLDERS</code>:
* 1: ‎<code>$HOME/.node_modules</code>
* 2: ‎<code>$HOME/.node_libraries</code>
* 3: ‎<code>$PREFIX/lib/node</code>
حيث <code>‎$HOME</code> هو المجلد الرئيسي للمستخدم، و <code>‎$PREFIX</code> هو بادئة <code>node_prefix</code> المُكوّنة لبيئة Node.js.
 
وهذا في الغالب لأسباب تاريخية.
وهذا في الغالب لأسباب تاريخية.
يُنصح بقوة بوضع الاعتماديات في مجلد node_modules المحلي. فستُحمَّل أسرع وتكون أكثر موثوقية.
مُغلِّف الوحدات (The module wrapper)
قبل تنفيذ التعليمات البرمجية في الوحدة، ستُغلِّفها Node.js بمغلف دوال يشبه ما يلي:


عند القيام بذلك، تحقق Node.js بضعة أشياء:
يُنصح بقوة بوضع الاعتماديات في مجلد <code>node_modules</code> المحلي. فستُحمَّل أسرع وتكون أكثر موثوقية.
    • تحفظ المتغيرات ذات المستوى الأعلى (المُعرَّفة مع var أو const أو let) في نطاق الوحدة بدلاً من نطاق الكائن العمومي.
 
    • ويساعد على توفير بعض متغيرات البحث العامة والتي تكون في الواقع مخصصة بالوحدة، مثل:
== مُغلِّف الوحدات (The module wrapper) ==
        ◦ كائنات module و exports التي يمكن للمُنفِّذ استخدامها لتصدير القيم من الوحدة.
قبل تنفيذ التعليمات البرمجية في الوحدة، ستُغلِّفها Node.js بمغلف دوال يشبه ما يلي:<syntaxhighlight lang="javascript">
        ◦ متغيرات المواءمة ‎__filename و ‎‎__dirname، التي تحتوي على اسم ملف الوحدة ومسار مجلده المطلقَين.
(function(exports, require, module, __filename, __dirname) {
نطاق الوحدة النمطية  
// تقع شيفرة الوحدة في الواقع هنا
‎‎__dirname
});
 
</syntaxhighlight>عند القيام بذلك، تحقق Node.js بضعة أشياء:
* تحفظ المتغيرات ذات المستوى الأعلى (المُعرَّفة مع <code>[[JavaScript/var|var]]</code> أو <code>[[JavaScript/const|const]]</code> أو <code>[[JavaScript/let|let]]</code>) في نطاق الوحدة بدلاً من نطاق الكائن العمومي.
* ويساعد على توفير بعض متغيرات البحث العامة والتي تكون في الواقع مخصصة بالوحدة، مثل:
** كائنات <code>module</code> و <code>exports</code> التي يمكن للمُنفِّذ استخدامها لتصدير القيم من الوحدة.
** متغيرات المواءمة <code>‎__filename</code> و ‎‎<code>__dirname</code>، التي تحتوي على اسم ملف الوحدة ومسار مجلده المطلقَين.
 
== نطاق الوحدة النمطية ==
 
=== ‎‎<code>__dirname</code> ===
أُضيف مع الإصدار: v0.1.27.
أُضيف مع الإصدار: v0.1.27.
    • من النوع <string>.
* من النوع [[JavaScript/String|<string>]].
اسم مجلد الوحدة الحالية. وهو مثل (path.dirname) في ‎__filename.
اسم مجلد الوحدة الحالية. وهو مثل <code>path.dirname()‎</code> في ‎<code>__filename</code>.
مثال: تشغيل node example.js من ‎/Users/mjr.


‎__filename
مثال: تشغيل <code>node example.js</code> من <code>‎/Users/mjr</code>.<syntaxhighlight lang="javascript">
console.log(__dirname);
// طباعة: /Users/mjr
console.log(path.dirname(__filename));
// طباعة: /Users/mjr
 
</syntaxhighlight>
 
=== <code>‎__filename</code> ===
أُضيف مع الإصدار: v0.0.1.
أُضيف مع الإصدار: v0.0.1.
    • من النوع <string>.
* من النوع [[JavaScript/String|<string>]].
اسم ملف الوحدة الحالية. وهو حل المسار المطلق لملف الوحدة الحالية.
اسم ملف الوحدة الحالية. وهو استبيان المسار المطلق لملف الوحدة الحالية.
 
ليس بالضرورة لبرنامج رئيسي أن يكون له نفس اسم الملف المستخدم في سطر الأوامر.
ليس بالضرورة لبرنامج رئيسي أن يكون له نفس اسم الملف المستخدم في سطر الأوامر.
راجع ‎‎__dirname لاسم مجلد الوحدة الحالية.
أمثلة
تشغيل node example.js من ‎/Users/mjr.


بالنظر إلى الوحدتين: a و b حيث b هو اعتمادية للوحدة a وتوجد بنية المجلد:
راجع ‎‎<code>__dirname</code> لاسم مجلد الوحدة الحالية.
    • /Users/mjr/app/a.js
 
    • /Users/mjr/app/node_modules/b/b.js
أمثلة: تشغيل <code>node example.js</code> من <code>‎/Users/mjr</code>.
المراجع إلى ‎__filename داخل b.js سيُعيد ‎/Users/mjr/app/node_modules/b/b.js في حين تعيد المراجع إلى ‎__filename داخل a.js القيمة ‎/Users/mjr/app/a.
 
exports
بالنظر إلى الوحدتين: <code>a</code> و <code>b</code> حيث <code>b</code> هو اعتمادية للوحدة <code>a</code> وتوجد بنية المجلد:
* ‎<code>/Users/mjr/app/a.js</code>
* ‎<code>/Users/mjr/app/node_modules/b/b.js</code>
المراجع إلى ‎<code>__filename</code> داخل <code>b.js</code> ستُعيد <code>‎/Users/mjr/app/node_modules/b/b.js</code> في حين تعيد المراجع إلى <code>‎__filename</code> داخل <code>a.js</code> القيمة <code>‎/Users/mjr/app/a</code>.
 
=== <code>exports</code> ===
أُضيف مع الإصدار: v0.1.12.
أُضيف مع الإصدار: v0.1.12.
هو مرجع إلى module.exports أقصر في الكتابة. راجع قسم exports shortcut للحصول على تفاصيل حول متى يمكن استخدام exports ومتى تُستخدم module.exports.
هو مرجع إلى <code>module.exports</code> أقصر في الكتابة. راجع قسم <code>exports shortcut</code> للحصول على تفاصيل حول متى يمكن استخدام <code>exports</code> ومتى تُستخدم module.exports.
module
 
=== <code>module</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
هو مرجع إلى الوحدة الحالية، راجع قسم كائن module object. ولا سيما تستخدمmodule.exports لتحديد ما تصدره الوحدة وتتيحه من خلال require()‎.
هو مرجع إلى الوحدة الحالية، راجع قسم كائن <code>module object</code>. ولا سيما <code>module.exports</code> لتحديد ما تصدره الوحدة وتتيحه من خلال <code>require()</code>‎.
require()‎
 
=== <code>require()‎</code> ===
أُضيف مع الإصدار: v0.1.13.
أُضيف مع الإصدار: v0.1.13.
    • من النوع <Function>
* من النوع [[JavaScript/Function|<Function>]].
لطلب الوحدات.
لطلب الوحدات.
require.cache
 
=== <code>require.cache</code> ===
أُضيف مع الإصدار: v0.3.0.
أُضيف مع الإصدار: v0.3.0.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
تُخزَّن الوحدات مؤقتًا في هذا الكائن عندما تكون مطلوبة. عند حذف قيمة مفتاحية من هذا الكائن، سيُعيد require التالي تحميل الوحدة. علما بأن هذا لا ينطبق على addons الأصلية، إذ تُنتج إعادة التحميل خطًأ.
تُخزَّن الوحدات مؤقتًا في هذا الكائن عندما تكون مطلوبة. عند حذف قيمة مفتاحية من هذا الكائن، سيُعيد require التالي تحميل الوحدة. علما بأن هذا لا ينطبق على addons الأصلية، إذ تُنتج إعادة التحميل خطأً.
require.extensions
=== <code>require.extensions</code> ===
أضيفت مع الإصدار: v0.3.0، وأُهمِلت مع الإصدار: v0.10.6.
أضيفت مع الإصدار: v0.3.0، وأُهمِلت مع الإصدار: v0.10.6.
مؤشر الاستقرار: 0 - مُهمَل
مؤشر الاستقرار: 0 - مُهمَل
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
إرشاد require حول كيفية التعامل مع بعض امتدادات الملفات.
إرشاد <code>require</code> حول كيفية التعامل مع بعض امتدادات الملفات.
معالجة الملفات بالامتداد ‎.sjs مثل ‎.js:
 
معالجة الملفات بالامتداد <code>‎.sjs</code> مثل <code>‎.js</code>:


مهملة في الماضي، استخدمت هذه القائمة لتحميل الوحدات غير JavaScript إلى Node.js بترجمتها حسب الطلب. ومع ذلك، في الممارسة العملية، هناك سبل أفضل للقيام بذلك، مثل تحميل الوحدات عن طريق بعض برامج Node.js الأخرى، أو ترجمتها إلى JavaScript قبل وقتها.
مهملة في الماضي، استخدمت هذه القائمة لتحميل الوحدات غير JavaScript إلى Node.js بترجمتها حسب الطلب. ومع ذلك، في الممارسة العملية، هناك سبل أفضل للقيام بذلك، مثل تحميل الوحدات عن طريق بعض برامج Node.js الأخرى، أو ترجمتها إلى JavaScript قبل وقتها.
لما كان نظام الوحدات مغلقًا، فربما لم تُلغى هذه الميزة أبدًا. ومع ذلك، فقد يكون بها أخطاء خفية وتعقيدات من الأفضل تركها بلا مساس.
لما كان نظام الوحدات مغلقًا، فربما لم تُلغى هذه الميزة أبدًا. ومع ذلك، فقد يكون بها أخطاء خفية وتعقيدات من الأفضل تركها بلا مساس.
علما بأن عدد عمليات نظام الملفات التي يجب على نظام الوحدات أداءها من أجل حل جملة require(...)‎ إلى اسم ملف يقاس خطيًا مع عدد الملحقات المسجلة.
علما بأن عدد عمليات نظام الملفات التي يجب على نظام الوحدات أداءها من أجل حل جملة require(...)‎ إلى اسم ملف يقاس خطيًا مع عدد الملحقات المسجلة.
وبعبارة أخرى، إضافة الملحقات يبطئ من تحميل الوحدة وينبغي تجنبها.
وبعبارة أخرى، إضافة الملحقات يبطئ من تحميل الوحدة وينبغي تجنبها.
require.main
 
<code>require.main</code>
 
أُضيفت مع الإصدار: v0.1.17.
أُضيفت مع الإصدار: v0.1.17.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
كائن الوحدة Module الذي يمثل سكربت الإدخال المُحمَّل عند بدء عملية Node.js. راجع "الوصول إلى الوحدة الرئيسية".
كائن الوحدة <code>Module</code> الذي يمثل سكربت الإدخال المُحمَّل عند بدء عملية Node.js. راجع "الوصول إلى الوحدة الرئيسية".
في سكربت entry.js:
 
في سكربت <code>entry.js</code>:<syntaxhighlight lang="javascript">
console.log(require.main);
 
</syntaxhighlight><syntaxhighlight lang="text">
node entry.js
 
</syntaxhighlight><syntaxhighlight lang="javascript">
Module {
  id: '.',
  exports: {},
  parent: null,
  filename: '/absolute/path/to/entry.js',
  loaded: false,
  children: [],
  paths:
  [ '/absolute/path/to/node_modules',
    '/absolute/path/node_modules',
    '/absolute/node_modules',
    '/node_modules' ] }
 
</syntaxhighlight><code>require.resolve(request[, options])‎</code>
{| class="wikitable"
!الإصدار
!التغييرات
|-
|v8.9.0
|دعم خيار <code>paths</code> الآن.
|-
|v0.3.0
|أُضيف مع الإصدار: v0.3.0.
|}
* <code>request</code> من النوع [[JavaScript/String|<string>]]: مسار الوحدة المراد حله.
* <code>options</code> من النوع <nowiki/>[[JavaScript/Object|<Object>]]:
** <code>paths</code> من النوع [[JavaScript/String|‎<string[]>]]‎: المسارات المراد حل موقع الوحدة من عندها. إذا كانت هذه المسارات موجودة، تستخدم بدلاً من مسارات الحل الافتراضية، باستثناء <code>GLOBAL_FOLDERS</code> مثل <code>‎$HOME/.node_modules</code> المُتضمَّن دائمًا. لاحظ أن كل من هذه المسارات تستخدم كنقطة انطلاق خوارزمية وحدة الحل، وهذا يعني أن التحقق من التسلسل الهرمي للمجلد <code>node_modules</code> يبدأ من هذا الموقع.
* القيمة المُعادة: من النوع <code><string></code>.
استخدام آلية <code>require()‎</code> الداخلية للبحث عن موقع وحدةٍ ما، ولكن بدلاً من تحميل الوحدة، يُعاد فقط اسم الملف المحلول.


require.resolve(request[, options])
=== <code>require.resolve.paths(request)‎</code> ===
الإصدار
التغييرات
v8.9.0
دعم خيار paths الآن.
v0.3.0
أُضيف مع الإصدار: v0.3.0.
    • request  من النوع <string>: مسار الوحدة المراد حله.
    • options من النوع  <Object>
        ◦ paths من النوع ‎<string[]>‎: المسارات المراد حل موقع الوحدة من عندها. إذا كانت هذه المسارات موجودة، تستخدم بدلاً من مسارات الحل الافتراضية، باستثناء GLOBAL_FOLDERS مثل  ‎$HOME/.node_modules المُتضمَّن دائماً. لاحظ أن كل من هذه المسارات تستخدم كنقطة انطلاق خوارزمية وحدة الحل، وهذا يعني أن التحقق من التسلسل الهرمي للمجلد node_modules يبدأ من هذا الموقع.
    • القيمة المُعادة: من النوع <string>.
استخدام آلات require()‎ الداخلية للبحث عن موقع وحدةٍ ما، ولكن بدلاً من تحميل الوحدة، يُعاد فقط اسم الملف المحلول.
require.resolve.paths(request)
أُضيف مع الإصدار: v8.9.0.
أُضيف مع الإصدار: v8.9.0.
    • request من النوع <string>: مسار الوحدة التي يُسترد مسارات البحث الخاصة بها.
* <code>request</code> من النوع [[JavaScript/String|<string>]]: مسار الوحدة التي يُسترد مسارات البحث الخاصة بها.
    • القيمة المُعادة: <string[]> | <null>
* القيمة المُعادة: ‎[[JavaScript/String|<string[]>]] | [[JavaScript/null|<null>]]‎.
إعادة مصفوفة تحتوي على المسارات التي بُحِثَ عنها خلال حل request أو null إذا كانت سلسلة request تشير إلى وحدة نواة، على سبيل المثال http أو fs.
إعادة مصفوفة تحتوي على المسارات التي بُحِثَ عنها خلال استبيان <code>request</code> أو <code>null</code> إذا كانت سلسلة <code>request</code> تشير إلى وحدة أساسية، على سبيل المثال <code>[[Node.js/http|http]]</code> أو <code>[[JavaScript/fs|fs]]</code>.
كائن module
 
== hgكائن <code>module</code> ==
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
في كل وحدة، يكون متغير module الحر مرجعًا للكائن الذي يمثل الوحدة الحالية. لمزيد من المواءمة، يمكن الوصول إلى module.exports أيضا عبر وحدة exports العامة. module ليست في الواقع عامة ولكنها بالأحرى محلية لكل وحدة.
في كل وحدة، يكون متغير <code>module</code> الحر مرجعًا للكائن الذي يمثل الوحدة الحالية. لمزيد من المواءمة، يمكن الوصول إلى <code>module.exports</code> أيضًا عبر وحدة <code>exports</code> العامة. <code>module</code> ليست في الواقع عامة ولكنها بالأحرى محلية لكل وحدة.
module.children
 
=== <code>module.children</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
    • من النوع ‎<module[]>‎
 
    • من النوع ‎<module[]>‎.
 
كائنات الوحدة المطلوبة من قِبلها.
كائنات الوحدة المطلوبة من قِبلها.
module.exports
 
=== <code>module.exports</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
يُنشِأ نظامُ Module كائنَ module.exports. في بعض الأحيان يكون هذا الأمر غير مقبول؛ يريد الكثير أن تكون وحدتهم مثيلة لصنف ما. للقيام بذلك، يجب تعيين الكائن المطلوب تصديره إلى module.exports. لاحظ أن تعيين الكائن المطلوب إلى  exports سيربط ببساطة متغيرexports المحلي، وهو على الأرجح ليس هو المطلوب.
يُنشِئ نظامُ <code>Module</code> كائنَ <code>module.exports</code>. في بعض الأحيان يكون هذا الأمر غير مقبول؛ يريد الكثير أن تكون وحدتهم مثيلة لصنف ما. للقيام بذلك، يجب تعيين الكائن المطلوب تصديره إلى <code>module.exports</code>. لاحظ أن تعيين الكائن المطلوب إلى <code>exports</code> سيربط ببساطة متغير <code>exports</code> المحلي، وهو على الأرجح ليس هو المطلوب.
على سبيل المثال لنفترض عمل وحدة تسمى a.js:


ثم في ملف آخر يمكننا أن نعمل:
على سبيل المثال لنفترض عمل وحدة تسمى <code>a.js</code>:<syntaxhighlight lang="javascript">
const EventEmitter = require('events');


علما بأن يجب أن تكون الإحالة إلى module.exports على الفور. ولا يمكن القيام بذلك في أي استدعاءات. فهذا لا يعمل:
module.exports = new EventEmitter();
x.js:


y.js:
// القيام ببعض العمل ، وبعد بعض الوقت إطلاق
// الحدث "ready" من الوحدة نفسها.
setTimeout(() => {
  module.exports.emit('ready');
}, 1000);


اختصار الصادرات
</syntaxhighlight>ثم في ملف آخر يمكننا أن نعمل:<syntaxhighlight lang="javascript">
const a = require('./a');
a.on('ready', () => {
  console.log('module "a" is ready');
});
 
</syntaxhighlight>علما بأن يجب أن تكون الإحالة إلى <code>module.exports</code> على الفور. ولا يمكن القيام بذلك في أي استدعاءات. فهذا لا يعمل:
 
<code>x.js</code>:<syntaxhighlight lang="javascript">
setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0);
 
</syntaxhighlight><code>y.js</code>:<syntaxhighlight lang="javascript">
const x = require('./x');
console.log(x.a);
 
</syntaxhighlight>
 
== اختصار الصادرات ==
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
متغير exports متاح داخل نطاق مستوى الملف الوحدة، ويُعيَّن بقيمة module.exports قبل تقييم الوحدة.
أنها تسمح باختصار، حتى أنه يمكن كتابة ‎module.exports.f = ...‎ بطريقة أكثر وضوحًا مثل  exports.f = ....‎ ومع ذلك، يجب الانتباه أنه مثل أي متغير، إذا عُيّنت exports بقيمة جديدة، فإنها لن تظل مرتبطة مع module.exports:


عندما يحل محل الخاصية module.exports كائن جديد بشكلٍ تام، فمن الشائع أن أيضا إعادة تعيين exports:
متغير <code>exports</code> متاح داخل نطاق مستوى الملف الوحدة، ويُعيَّن بقيمة <code>module.exports</code> قبل تقييم الوحدة.
 
أنها تسمح باختصار، حتى أنه يمكن كتابة ‎<code>module.exports.f = ...‎</code> بطريقة أكثر وضوحًا مثل  <code>exports.f = ....‎</code> ومع ذلك، يجب الانتباه أنه مثل أي متغير، إذا عُيّنت <code>exports</code> بقيمة جديدة، فإنها لن تظل مرتبطة مع <code>module.exports</code>:<syntaxhighlight lang="javascript">
module.exports.hello = true; // مُصدَّر من متطلبات الوحدة
exports = { hello: false };  // لم يصدَّر ، متوفر فقط في الوحدة
 
</syntaxhighlight>عندما يحل محل الخاصية module.exports كائن جديد بشكلٍ تام، فمن الشائع أن أيضا إعادة تعيين exports:<syntaxhighlight lang="javascript">
module.exports = exports = function Constructor() {
  // ... إلخ.
};
 
</syntaxhighlight>لتوضيح السلوك، تخيل هذا التنفيذ الافتراضي للتابع <code>require()‎</code>، والذي يماثل تمامًا ما يقوم به فعلًا <code>require()‎</code>:<syntaxhighlight lang="javascript">
function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // شيفرة الوحدة هنا. في هذا المثال ، تحدد دالة.
    function someFunc() {}
    exports = someFunc;
    // عند هذه النقطة ، لم تعد الصادرات اختصارًا لـ module.exports ،
    // وستستمر هذه الوحدة في تصدير كائن افتراضي فارغ.
    module.exports = someFunc;
    / / عند هذه النقطة ، ستقوم الوحدة الآن بتصدير someFunc ، بدلاً من
    // default object.
  })(module, module.exports);
  return module.exports;
}


لتوضيح السلوك، تخيل هذا التنفيذ الافتراضي للتابع require()‎، والذي يماثل تماما ما يقوم به فعلا require()‎:
</syntaxhighlight><code>module.filename</code>


module.filename
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
    • من النوع <string>.
* من النوع [[JavaScript/String|<string>]].
اسم الملف المحلول بالكامل للوحدة.
اسم الملف المستبين بالكامل للوحدة.
module.id
 
=== <code>module.id</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
    • من النوع <string>.
* من النوع [[JavaScript/String|<string>]].
معرف الوحدة. عادة هو اسم الملف المحلول بالكامل.
معرف الوحدة. عادة هو اسم الملف المحلول بالكامل.
module.loaded
 
=== <code>module.loaded</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
    • من النوع <boolean>
* من النوع [[JavaScript/Boolean|<boolean>]].
ما إذا كان قد انتهى تحميل الوحدة أم لا، أو لا يزال في عملية التحميل.
ما إذا كان قد انتهى تحميل الوحدة أم لا، أو ما يزال في عملية التحميل.
module.parent
 
=== <code>module.parent</code> ===
أُضيف مع الإصدار: v0.1.16.
أُضيف مع الإصدار: v0.1.16.
    • من النوع <module>
 
    • من النوع <module>.
 
الوحدة التي تتطلبها أولاً.
الوحدة التي تتطلبها أولاً.
module.paths
 
=== <code>module.paths</code> ===
أُضيف مع الإصدار: v0.4.0.
أُضيف مع الإصدار: v0.4.0.
    • من النوع <string[]>
*  من النوع [[JavaScript/String|<string[]>]].
مسارات البحث عن الوحدة.
مسارات البحث عن الوحدة.
module.require(id)
 
=== <code>module.require(id)‎</code> ===
أُضيف مع الإصدار: v0.5.1.
أُضيف مع الإصدار: v0.5.1.
    • id من النوع <string>
* <code>id</code> من النوع [[JavaScript/String|<string>]].
    • القيمة المُعادة: <Object> من النوع module.exports من الوحدة المحلولة.
القيمة المُعادة: [[JavaScript/Object|<Object>]] من النوع <code>module.exports</code> من الوحدة المستبينة.
يوفر التابع module.require طريقة لتحميل الوحدة كما لو اُستدعِي require()‎ من الوحدة الأصلية.
 
للقيام بذلك، من الضروري الحصول على مرجع إلى كائن module. لما كان require()‎ يعيد module.exports، وتتوفر module عادة في التعليمات البرمجية فقط لوحدة معينة، فإنه يجب تصديرها صراحة من أجل استخدامها.
يوفر التابع <code>module.require</code> طريقة لتحميل الوحدة كما لو اُستدعِي <code>require()‎</code> من الوحدة الأصلية.
كائن Module
 
للقيام بذلك، من الضروري الحصول على مرجع إلى كائن <code>module</code>. لما كان <code>require()‎</code> يعيد <code>module.exports</code>، وتتوفر <code>module</code> عادة في التعليمات البرمجية فقط لوحدة معينة، فإنه يجب تصديرها صراحة من أجل استخدامها.
 
== كائن <code>Module</code> ==
أُضيف مع الإصدار: v0.3.7.
أُضيف مع الإصدار: v0.3.7.
من النوع <nowiki><Object>.</nowiki>
* من النوع [[JavaScript/Object|<Object>]].
يوفر توابع خدمة عامة عند التعامل مع نسخ من الوحدة Module –غالباً ما يُرى متغير module في وحدات الملف. الوصول إليها عن طريق require('module').
يوفر توابع خدمة عامة عند التعامل مع نسخ من الوحدة Module –غالباً ما يُرى متغير module في وحدات الملف. الوصول إليها عن طريق require('module').
module.builtinModules
 
=== <code>module.builtinModules</code> ===
أُضيف مع الإصدار: v9.3.0.
أُضيف مع الإصدار: v9.3.0.
    • من النوع ‎<string[]>‎.
* من النوع ‎[[JavaScript/String|<string[]>‎]].
قائمة بأسماء كافة الوحدات التي توفرها Node.js. يمكن استخدامها للتحقق من إذا كان الوحدة تُصان من قِبَل طرف ثالث أو لا.
قائمة بأسماء كافة الوحدات التي توفرها Node.js. يمكن استخدامها للتحقق من إذا كان الوحدة تُصان من قِبَل طرف ثالث أو لا.
لاحظ أن الوحدة module في هذا السياق ليست نفس الكائن الذي توفره وحدة التغليف module wrapper. للوصول إليها، يجب طلب الوحدة Module:
 
لاحظ أن الوحدة <code>module</code> في هذا السياق ليست نفس الكائن الذي توفره وحدة التغليف module wrapper. للوصول إليها، يجب طلب الوحدة <code>Module</code>:<syntaxhighlight lang="javascript">
const builtin = require('module').builtinModules;
const builtin = require('module').builtinModules;
</syntaxhighlight>
== مصادر ==
* [https://nodejs.org/dist/latest-v10.x/docs/api/modules.html صفحة Modules في توثيق Node.js الرسمي].
[[تصنيف:Node.js|{{SUBPAGENAME}}]]

المراجعة الحالية بتاريخ 11:17، 23 أكتوبر 2018

مؤشر الاستقرار: 2 - مستقر

يعامل كل ملف في نظام الوحدات في بيئة Node.js كوحدة منفصلة. على سبيل المثال، فليكن ملف اسمه foo.js:

const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);

في السطر الأول، يُحمِّل foo.js الوحدة circle.js الموجودة في نفس المجلد مع foo.js. وإليك محتويات circle.js:

const { PI } = Math;

exports.area = (r) => PI * r ** 2;

exports.circumference = (r) => 2 * PI * r;

صدَّرت الوحدة circle.js الدالتين area()‎ و circumference()‎. وتُضاف الدوال والكائنات إلى جذر الوحدة بتعيين خصائص إضافية لكائن الصادرات exports الخاص.

ستكون المتغيرات المحلية في الوحدة خاصة، نظرًا لأن الوحدة مغلفة في دالة بواسطة Node.js (انظر مُغلِّف الوحدات module wrapper). في هذا المثال، يكون المتغير PI خاصًا بالوحدة circle.js.

يمكن تعيين الخاصية module.exports بقيمة جديدة (مثل دالة أو الكائن).

فيما يلي، يستخدم bar.js الوحدة square، التي تُصدِّر الصنف Square:

const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`);

الوحدة square مُعرفَّة في square.js:

// assigning to exports will not modify module, must use module.exports
module.exports = class Square {
  constructor(width) {
    this.width = width;
  }

  area() {
    return this.width ** 2;
  }
};

ويتحقق نظام الوحدات في الوحدة require('module')‎.

الوصول إلى الوحدة الرئيسية

عند تشغيل ملف مباشرة من Node.js، تُضبط الخاصية require.main إلى وحدتها module. وهذا يعني أنه من الممكن تحديد ما إذا كان قد جرى تشغيل ملفٍ ما مباشرة عن طريق اختبار require.main === module.

بالنسبة لملف foo.js، ستكون قيمتها true إذا نُفِذت عبر node foo.js لكن تكون false إذا نُفِذت عبر require('./foo')‎.

ولمّا كانت الوحدة module توفر الخاصية filename (عادة ما تكافئ ‎‎__filename) فيمكن الحصول على نقطة الدخول من التطبيق الحالي عن طريق فحص require.main.filename.

Addenda: نصائح عن مدير الحِزم

صُممت دلالات الدالة require()‎ في Node.js لتكون عامة بما يكفي لدعم عدد من هياكل المجلدات المعقولة. تأمل تطبيقات إدارة حِزم البرامج مثل dpkg و rpm و npm، تجد أنه من الممكن بناء حزم أصلية من وحدات Node.js دون تعديل.

فيما يلي مُقترح بنية مُجلد والتي يمكن أن تعمل:

لنفرض أننا نريد أن يحتوي المجلد ‎/usr/lib/node/<some-package>/<some-version>‎ على محتويات إصدار محدد لحزمةٍ ما.

يمكن أن تعتمد الحزم على بعضها البعض. فمن أجل تثبيت الحزمة foo، قد يلزم تثبيت إصدار محدد من الحزمة bar. وقد يكون للحزمة bar نفسها ‫اعتماديات، وفي بعض الحالات، قد تتعارض أو تشكل اعتماديات دورية.

ولما كانت Node.js تبحث عن المسار الحقيقي realpath للوحدات التي تُحمِّلها (أي، تستبين الوصلات الرمزية)، ومن ثَمَّ يبحث عن اعتمادياتها في مجلدات node_modules، ويُعد هذا الوضع بسيط جدًا للحل مع البنية التالية:

  • /usr/lib/node/foo/1.2.3/‎‎‎: محتويات حزمة foo، الإصدار 1.2.3.
  • /usr/lib/node/bar/4.3.2/‎‎: محتويات حزمة bar التي تعتمد عليها حزمة foo.
  • /‎/‎usr/lib/node/foo/1.2.3/node_modules/bar: وصلة رمزية تشير إلى /usr/lib/node/bar/4.3.2/.
  • /‎‎usr/lib/node/bar/4.3.2/node_modules/‎*‎: وصلة رمزية تشير إلى الحزمة التي تعتمد عليها الحزمة bar.

وهكذا، حتى إذا صودفت دورة، أو إذا كان هناك تعارضات في الاعتمادية، ستكون كل وحدة قادرةً على الحصول على نسخة الاعتمادية التي يمكن أن تستخدمها.

عندما تحتاج التعليمات البرمجية في حزمة foo إلى استدعاء require('bar')‎، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية ‎/usr/lib/node/foo/1.2.3/node_modules/bar. كذلك، عندما تحتاج التعليمات البرمجية في حزمة bar إلى استدعاء require('quux')‎، سوف تحصل على النسخة التي يشار إليها من الوصلة الرمزية ‎/usr/lib/node/bar/4.3.2/node_modules/quux.

وعلاوة على ذلك, لجعل عملية البحث في الوحدة أحسن أداءً، يمكن وضع الحزم في‎/usr/lib/node_modules/<name>/<version>‎ بدلًا من وضعها مباشرة في ‎/usr/lib/node. لا تهتم Node.js بالبحث عن الاعتماديات المفقودة في ‎/usr/node_modules أو ‎/node_modules.

لإتاحة الوحدات لـ Node.js REPL، قد يكون من المفيد أيضًا إضافة المجلد ‎/usr/lib/node_modules إلى متغير البيئة ‎$NODE_PATH. ولما كان البحث في الوحدات باستخدام المجلدات node_modules نسبيًا، واستنادا إلى المسار الحقيقي لملفات استدعاء require()‎، يمكن أن تكون الحزم نفسها في أي مكان.

خلاصة الكلام السابق

تُستخدم الدالة require.resolve()‎ للحصول على اسم الملف الصحيح الذي سيُحمَّل عند استدعاء require()‎.

بتجميع كل ما سبق، فيما يلي خوارزمية رفيعة المستوى في شكل شيفرة وهمية (pseudocode) عما يجريه require.resolve()‎:

require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with '/'
   a. set Y to be the filesystem root
3. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
4. LOAD_NODE_MODULES(X, dirname(Y))
5. THROW "not found"

LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.json is a file, parse X.json to a JavaScript Object.  STOP
4. If X.node is a file, load X.node as binary addon.  STOP

LOAD_INDEX(X)
1. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon.  STOP

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
   d. LOAD_INDEX(M)
2. LOAD_INDEX(X)

LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_AS_FILE(DIR/X)
   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = [GLOBAL_FOLDERS]
4. while I >= 0,
   a. if PARTS[I] = "node_modules" CONTINUE
   b. DIR = path join(PARTS[0 .. I] + "node_modules")
   c. DIRS = DIRS + DIR
   d. let I = I - 1
5. return DIRS

التخزين المؤقت (Caching)

تُخزَّن الوحدات مؤقتًا بعد تحميلها أول مرة. وهذا يعني (من ضمن أمور أخرى) أن كل استدعاء للتابع require('foo')‎ سوف يعيد بالضبط الكائن نفسه إذ كان يحل نفس الملف.

قد لا تسبب عدة استدعاءات للتابع require('foo')‎ تنفيذ شيفرة الوحدة عدة مرات. وهي ميزة هامة. مع ذلك، يمكن إعادة الكائنات "المُنفَّذة جزئيًا"، مما يسمح بتحميل الاعتماديات الانتقالية حتى عندما تتسبب في دورات.

لتنفيذ التعليمات البرمجية لوحدة عدة مرات يجب تصدير دالة واستدعاء هذه الدالة.

محاذير التخزين المؤقت للوحدات

تُخزين الوحدات مؤقتاً على أساس حل اسم الملف. لما كان حل الوحدات إلى اسم ملف مختلف على أساس موقع الوحدة المُستدعِية (تحميل من مجلدات node_modules)، فإنه لا يضمن أن يُعيد التابع require('foo')‎ دائمًا نفس الكائن بالضبط، إذا كان يحل لملفات مختلفة.

بالإضافة إلى ذلك، في أنظمة الملفات أو أنظمة التشغيل الحساسة لحالة الأحرف، يمكن أن تشير الأسماء المحلولة المختلفة إلى نفس الملف، ولكن ذاكرة التخزين المؤقت ستستمر في التعامل معها كوحدات مختلفة، وستُحمل الملف عدة مرات. على سبيل المثال، يعيد كلٌ من require('./foo')‎ و require('./FOO')‎ كائنين مختلفين، بغض النظر عن ما إذا كان  ‎./foo و ‎./FOO هما نفس الملف.

الوحدات الأساسية

تتمتع بيئة Node.js بالعديد من الوحدات المترجمة إلى النظام الثنائي. وتوصف هذه الوحدات بمزيد من التفصيل في مكان آخر من هذا التوثيق.

وتُعرَّف الوحدات الأساسية داخل مصدر Node.js وهي موجودة في المجلد lib/‎.

وتُحمَّل الوحدات الأساسية دائمًا بشكل تفضيلي إذا مُرر المعرف الخاص بها إلى require()‎. على سبيل المثال، يعيد require('http')‎ دائماً وحدة HTTP المُضمَّنة، حتى إذا كان هناك ملف بهذا الاسم.

الدورات

عندما تكون هناك استدعاءات require()‎ دائرية، قد لا تنتهي الوحدة من التنفيذ عند إعادتها.

إليك هذه الحالة:

a.js:

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');

b.js:

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');

main.js:

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done);

عند تحميل main.js للوحدة a.js، ثم تحمِّل a.js بدورها الوحدةَ b.js. عند هذه النقطة، تحاول b.js لتحميل a.js. من أجل منع حلقة لا نهائية، تُعاد نسخة غير مكتملة لكائن exports الخاص بالوحدة a.js إلى الوحدة b.js. ثم تنهي الوحدة b.js التحميل، وتُعيد كائن exports إلى الوحدة a.js. عند تحميل main.js لكلتا الوحدتين، تنتهي كل منهما. سيكون الناتج من هذا البرنامج بالتالي هو:

$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true

التخطيط الدقيق مطلوب للسماح لاعتماديات الوحدات النمطية كي تعمل بشكل صحيح داخل أي تطبيق.

وحدات الملفات

إذا لم يُعثر على اسم الملف الصحيح، ستحاول Node.js تحميل اسم الملف المطلوب مع امتدادات إضافية: ‎.js و ‎.json، وأخيراً ‎.node.

تُفسر ملفات ‎.js على أنها ملفات JavaScript نصية، وثُحلَّل الملفات ‎.json كملفات JSON نصية.  وتُفسَّر ملفات ‎.node كوحدات مُترجَمة مُلحَقة ومُحمَّلة مع dlopen.

الوحدة المُستدعاة المسبوقة بالعلامة '/' تمثل المسار المطلق للملف. على سبيل المثال، سيُحمِّل require('/home/marco/foo.js')‎ الملف ‎/home/marco/foo.js.

تمثل الوحدة المُستدعاة المسبوقة بالعلامة '/.' المسار النسبي للملف المُستدعي require()‎. فيجب أن يكون circle.js في نفس المجلد مع foo.js حتى يتمكن require('./circle')‎ من العثور عليه.

بدون البادئة '/' أو ‎‎'‎./'‎ أو ‎'../'‎ للإشارة إلى ملف، يجب أن تكون الوحدة وحدةً أساسيةً أو أن تكون مُحملة من مجلد node_modules.

إذا كان المسار غير موجود، سوف يلقي require()‎ الخطأ Error مع رمز الخاصية code بالقيمة 'MODULE_NOT_FOUND'.

المجلدات كوحدات

من الملائم تنظيم البرامج والمكتبات في مجلدات متضمنة ذاتيًا، ومن ثَمَّ توفير نقطة دخول واحدة إلى المكتبة. هناك ثلاث طرق لتمرير مجلد إلى require()‎ كوسيط.

الأولى عن طريق إنشاء ملف package.json في جذر المجلد، الذي يحدد وحدة رئيسية main. مثال لملف package.json قد يبدو كما يلي:

{ "name" : "some-library",
  "main" : "./lib/some-library.js" }

إذا كان هذا في مجلد ‎./some-library، فسيحاول التعبير require('./some-library')‎ تحميل ‎./some-library/lib/some-library.js.

هذا هو مدى تمييز Node.js لملفات package.json.

إذا كان الملف المحدد بواسطة المُدخَل الرئيسي 'main' هو package.json مفقود ولا يمكن أن يُستبين، سيُبلِغ Node.js أن الوحدة كاملةً مفقودة بسبب الخطأ الافتراضي:

Error: Cannot find module 'some-library'

إذا لم يكن هناك أي ملف package.json موجودًا في المجلد، ستحاول Node.js تحميل ملف index.js أو index.node من داخل هذا المجلد. على سبيل المثال، إذا لم يكن هناك أي ملف package.json في المثال أعلاه، سيحاول require('./some-library')‎ عندئذ تحميل:

  • ‎./some-library/index.js
  • ‎./some-library/index.node

التحميل من مجلدات node_modules

إذا كان مُعرِّف الوحدة المُمررة إلى require()‎ ليس وحدة نواة core، ولا يبدأ مع '/' أو ‎../'‎' أو '‎./‎'، ثم تبدأ Node.js من المجلد الأصل للوحدة الحالية، وتضيف ‎/node_modules، وتحاول تحميل الوحدة من ذلك الموقع. لن تلحق Node المجلد node_modules إلى مسار منتهي بالفعل بالسلسلة النصية node_modules. إذا لم يكن موجودًا، ينتقل إلى المجلد الأصل، وهلم جرًا، حتى يصل إلى جذر نظام الملفات.

على سبيل المثال، إذا كان الملف في ‎'/home/ry/projects/foo.js'‎ يستدعي require('bar.js')‎، فسوف تبحث Node.js في المواقع التالية بهذا الترتيب:

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

وهذا يسمح للبرامج بتحديد مواقع اعتمادياتها بحيث لا تتصادم. فمن الممكن طلب ملفات محددة أو وحدات فرعية موزعة مع وحدة عن طريق تضمين مسار لاحق بعد اسم الوحدة. فعلى سبيل المثال سيحل require('example-module/path/to/file')‎ إلى الملف path/to/file بالنسبة إلى حيث يوجد example-module. ويتبع المسار الملحق نفس دلالات حل الوحدات.

التحميل من المجلدات العامة

إذا ضُبط متغير البيئة NODE_PATH على قائمة مسارات مطلقة محددة بنقطتين رأسيتين ':'، ستبحث Node.js في تلك المسارات عن وحدات إذا لم تكن موجودة في أماكن أخرى. في ويندوز، يُحدد NODE_PATH بواسطة فاصلة منقوطة ';' بدلاً من النقطتين الرأسيتين ':'.

أُنشئت NODE_PATH أصلاً لدعم تحميل الوحدات من مسارات مختلفة قبل تجميد خوارزمية حل الوحدة الحالية.

ما تزال NODE_PATH مدعومة، ولكن ليس من الضروري أن يستقر نظام Node.js الإيكولوجي على تقليدٍ ما لتحديد أماكن الوحدات التابعة. في بعض الأحيان تُظهر عمليات النشر التي تعتمد على NODE_PATH سلوكًا غريبًا عند عدم تعيين NODE_PATH. في بعض الأحيان تغيير اعتماديات الوحدة، مما يتسبب في تحميل إصدار مختلف (أو حتى وحدة مختلفة) أثناء البحث في NODE_PATH.

بالإضافة إلى ذلك، ستبحث Node.js في القائمة التالية من GLOBAL_FOLDERS:

  • 1: ‎$HOME/.node_modules
  • 2: ‎$HOME/.node_libraries
  • 3: ‎$PREFIX/lib/node

حيث ‎$HOME هو المجلد الرئيسي للمستخدم، و ‎$PREFIX هو بادئة node_prefix المُكوّنة لبيئة Node.js.

وهذا في الغالب لأسباب تاريخية.

يُنصح بقوة بوضع الاعتماديات في مجلد node_modules المحلي. فستُحمَّل أسرع وتكون أكثر موثوقية.

مُغلِّف الوحدات (The module wrapper)

قبل تنفيذ التعليمات البرمجية في الوحدة، ستُغلِّفها Node.js بمغلف دوال يشبه ما يلي:

(function(exports, require, module, __filename, __dirname) {
// تقع شيفرة الوحدة في الواقع هنا
});

عند القيام بذلك، تحقق Node.js بضعة أشياء:

  • تحفظ المتغيرات ذات المستوى الأعلى (المُعرَّفة مع var أو const أو let) في نطاق الوحدة بدلاً من نطاق الكائن العمومي.
  • ويساعد على توفير بعض متغيرات البحث العامة والتي تكون في الواقع مخصصة بالوحدة، مثل:
    • كائنات module و exports التي يمكن للمُنفِّذ استخدامها لتصدير القيم من الوحدة.
    • متغيرات المواءمة ‎__filename و ‎‎__dirname، التي تحتوي على اسم ملف الوحدة ومسار مجلده المطلقَين.

نطاق الوحدة النمطية

‎‎__dirname

أُضيف مع الإصدار: v0.1.27.

اسم مجلد الوحدة الحالية. وهو مثل path.dirname()‎ في ‎__filename.

مثال: تشغيل node example.js من ‎/Users/mjr.

console.log(__dirname);
// طباعة: /Users/mjr
console.log(path.dirname(__filename));
// طباعة: /Users/mjr

‎__filename

أُضيف مع الإصدار: v0.0.1.

اسم ملف الوحدة الحالية. وهو استبيان المسار المطلق لملف الوحدة الحالية.

ليس بالضرورة لبرنامج رئيسي أن يكون له نفس اسم الملف المستخدم في سطر الأوامر.

راجع ‎‎__dirname لاسم مجلد الوحدة الحالية.

أمثلة: تشغيل node example.js من ‎/Users/mjr.

بالنظر إلى الوحدتين: a و b حيث b هو اعتمادية للوحدة a وتوجد بنية المجلد:

  • /Users/mjr/app/a.js
  • /Users/mjr/app/node_modules/b/b.js

المراجع إلى ‎__filename داخل b.js ستُعيد ‎/Users/mjr/app/node_modules/b/b.js في حين تعيد المراجع إلى ‎__filename داخل a.js القيمة ‎/Users/mjr/app/a.

exports

أُضيف مع الإصدار: v0.1.12. هو مرجع إلى module.exports أقصر في الكتابة. راجع قسم exports shortcut للحصول على تفاصيل حول متى يمكن استخدام exports ومتى تُستخدم module.exports.

module

أُضيف مع الإصدار: v0.1.16.

هو مرجع إلى الوحدة الحالية، راجع قسم كائن module object. ولا سيما module.exports لتحديد ما تصدره الوحدة وتتيحه من خلال require()‎.

require()‎

أُضيف مع الإصدار: v0.1.13.

لطلب الوحدات.

require.cache

أُضيف مع الإصدار: v0.3.0.

تُخزَّن الوحدات مؤقتًا في هذا الكائن عندما تكون مطلوبة. عند حذف قيمة مفتاحية من هذا الكائن، سيُعيد require التالي تحميل الوحدة. علما بأن هذا لا ينطبق على addons الأصلية، إذ تُنتج إعادة التحميل خطأً.

require.extensions

أضيفت مع الإصدار: v0.3.0، وأُهمِلت مع الإصدار: v0.10.6. مؤشر الاستقرار: 0 - مُهمَل

إرشاد require حول كيفية التعامل مع بعض امتدادات الملفات.

معالجة الملفات بالامتداد ‎.sjs مثل ‎.js:

مهملة في الماضي، استخدمت هذه القائمة لتحميل الوحدات غير JavaScript إلى Node.js بترجمتها حسب الطلب. ومع ذلك، في الممارسة العملية، هناك سبل أفضل للقيام بذلك، مثل تحميل الوحدات عن طريق بعض برامج Node.js الأخرى، أو ترجمتها إلى JavaScript قبل وقتها.

لما كان نظام الوحدات مغلقًا، فربما لم تُلغى هذه الميزة أبدًا. ومع ذلك، فقد يكون بها أخطاء خفية وتعقيدات من الأفضل تركها بلا مساس.

علما بأن عدد عمليات نظام الملفات التي يجب على نظام الوحدات أداءها من أجل حل جملة require(...)‎ إلى اسم ملف يقاس خطيًا مع عدد الملحقات المسجلة.

وبعبارة أخرى، إضافة الملحقات يبطئ من تحميل الوحدة وينبغي تجنبها.

require.main

أُضيفت مع الإصدار: v0.1.17.

كائن الوحدة Module الذي يمثل سكربت الإدخال المُحمَّل عند بدء عملية Node.js. راجع "الوصول إلى الوحدة الرئيسية".

في سكربت entry.js:

console.log(require.main);
node entry.js
Module {
  id: '.',
  exports: {},
  parent: null,
  filename: '/absolute/path/to/entry.js',
  loaded: false,
  children: [],
  paths:
   [ '/absolute/path/to/node_modules',
     '/absolute/path/node_modules',
     '/absolute/node_modules',
     '/node_modules' ] }

require.resolve(request[, options])‎

الإصدار التغييرات
v8.9.0 دعم خيار paths الآن.
v0.3.0 أُضيف مع الإصدار: v0.3.0.
  • request من النوع <string>: مسار الوحدة المراد حله.
  • options من النوع <Object>:
    • paths من النوع ‎<string[]>‎: المسارات المراد حل موقع الوحدة من عندها. إذا كانت هذه المسارات موجودة، تستخدم بدلاً من مسارات الحل الافتراضية، باستثناء GLOBAL_FOLDERS مثل ‎$HOME/.node_modules المُتضمَّن دائمًا. لاحظ أن كل من هذه المسارات تستخدم كنقطة انطلاق خوارزمية وحدة الحل، وهذا يعني أن التحقق من التسلسل الهرمي للمجلد node_modules يبدأ من هذا الموقع.
  • القيمة المُعادة: من النوع <string>.

استخدام آلية require()‎ الداخلية للبحث عن موقع وحدةٍ ما، ولكن بدلاً من تحميل الوحدة، يُعاد فقط اسم الملف المحلول.

require.resolve.paths(request)‎

أُضيف مع الإصدار: v8.9.0.

  • request من النوع <string>: مسار الوحدة التي يُسترد مسارات البحث الخاصة بها.
  • القيمة المُعادة: ‎<string[]> | <null>‎.

إعادة مصفوفة تحتوي على المسارات التي بُحِثَ عنها خلال استبيان request أو null إذا كانت سلسلة request تشير إلى وحدة أساسية، على سبيل المثال http أو fs.

hgكائن module

أُضيف مع الإصدار: v0.1.16.

في كل وحدة، يكون متغير module الحر مرجعًا للكائن الذي يمثل الوحدة الحالية. لمزيد من المواءمة، يمكن الوصول إلى module.exports أيضًا عبر وحدة exports العامة. module ليست في الواقع عامة ولكنها بالأحرى محلية لكل وحدة.

module.children

أُضيف مع الإصدار: v0.1.16.

    • من النوع ‎<module[]>‎.

كائنات الوحدة المطلوبة من قِبلها.

module.exports

أُضيف مع الإصدار: v0.1.16.

يُنشِئ نظامُ Module كائنَ module.exports. في بعض الأحيان يكون هذا الأمر غير مقبول؛ يريد الكثير أن تكون وحدتهم مثيلة لصنف ما. للقيام بذلك، يجب تعيين الكائن المطلوب تصديره إلى module.exports. لاحظ أن تعيين الكائن المطلوب إلى exports سيربط ببساطة متغير exports المحلي، وهو على الأرجح ليس هو المطلوب.

على سبيل المثال لنفترض عمل وحدة تسمى a.js:

const EventEmitter = require('events');

module.exports = new EventEmitter();

// القيام ببعض العمل ، وبعد بعض الوقت إطلاق
// الحدث "ready" من الوحدة نفسها.
setTimeout(() => {
  module.exports.emit('ready');
}, 1000);

ثم في ملف آخر يمكننا أن نعمل:

const a = require('./a');
a.on('ready', () => {
  console.log('module "a" is ready');
});

علما بأن يجب أن تكون الإحالة إلى module.exports على الفور. ولا يمكن القيام بذلك في أي استدعاءات. فهذا لا يعمل: x.js:

setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0);

y.js:

const x = require('./x');
console.log(x.a);

اختصار الصادرات

أُضيف مع الإصدار: v0.1.16.

متغير exports متاح داخل نطاق مستوى الملف الوحدة، ويُعيَّن بقيمة module.exports قبل تقييم الوحدة.

أنها تسمح باختصار، حتى أنه يمكن كتابة ‎module.exports.f = ...‎ بطريقة أكثر وضوحًا مثل  exports.f = ....‎ ومع ذلك، يجب الانتباه أنه مثل أي متغير، إذا عُيّنت exports بقيمة جديدة، فإنها لن تظل مرتبطة مع module.exports:

module.exports.hello = true; // مُصدَّر من متطلبات الوحدة
exports = { hello: false };  // لم يصدَّر ، متوفر فقط في الوحدة

عندما يحل محل الخاصية module.exports كائن جديد بشكلٍ تام، فمن الشائع أن أيضا إعادة تعيين exports:

module.exports = exports = function Constructor() {
  // ... إلخ.
};

لتوضيح السلوك، تخيل هذا التنفيذ الافتراضي للتابع require()‎، والذي يماثل تمامًا ما يقوم به فعلًا require()‎:

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // شيفرة الوحدة هنا. في هذا المثال ، تحدد دالة.
    function someFunc() {}
    exports = someFunc;
    // عند هذه النقطة ، لم تعد الصادرات اختصارًا لـ module.exports ،
    // وستستمر هذه الوحدة في تصدير كائن افتراضي فارغ.
    module.exports = someFunc;
    / / عند هذه النقطة ، ستقوم الوحدة الآن بتصدير someFunc ، بدلاً من
    // default object.
  })(module, module.exports);
  return module.exports;
}

module.filename

أُضيف مع الإصدار: v0.1.16.

اسم الملف المستبين بالكامل للوحدة.

module.id

أُضيف مع الإصدار: v0.1.16.

معرف الوحدة. عادة هو اسم الملف المحلول بالكامل.

module.loaded

أُضيف مع الإصدار: v0.1.16.

ما إذا كان قد انتهى تحميل الوحدة أم لا، أو ما يزال في عملية التحميل.

module.parent

أُضيف مع الإصدار: v0.1.16.

    • من النوع <module>.

الوحدة التي تتطلبها أولاً.

module.paths

أُضيف مع الإصدار: v0.4.0.

مسارات البحث عن الوحدة.

module.require(id)‎

أُضيف مع الإصدار: v0.5.1.

القيمة المُعادة: <Object> من النوع module.exports من الوحدة المستبينة.

يوفر التابع module.require طريقة لتحميل الوحدة كما لو اُستدعِي require()‎ من الوحدة الأصلية.

للقيام بذلك، من الضروري الحصول على مرجع إلى كائن module. لما كان require()‎ يعيد module.exports، وتتوفر module عادة في التعليمات البرمجية فقط لوحدة معينة، فإنه يجب تصديرها صراحة من أجل استخدامها.

كائن Module

أُضيف مع الإصدار: v0.3.7.

يوفر توابع خدمة عامة عند التعامل مع نسخ من الوحدة Module –غالباً ما يُرى متغير module في وحدات الملف. الوصول إليها عن طريق require('module').

module.builtinModules

أُضيف مع الإصدار: v9.3.0.

قائمة بأسماء كافة الوحدات التي توفرها Node.js. يمكن استخدامها للتحقق من إذا كان الوحدة تُصان من قِبَل طرف ثالث أو لا.

لاحظ أن الوحدة module في هذا السياق ليست نفس الكائن الذي توفره وحدة التغليف module wrapper. للوصول إليها، يجب طلب الوحدة Module:

const builtin = require('module').builtinModules;

مصادر