Menu
العربية

بيئة تشغيل Node.js: كيف تعمل JavaScript خارج المتصفح

تعرّف على بيئة تشغيل Node.js، وكيف تختلف عن المتصفح، وأهم الواجهات المدمجة مثل process و fs والوحدات التي تجعل تشغيل JavaScript على الخادم ممكنًا.

ما هو Node.js فعلياً؟

باختصار، Node.js هو برنامج تُثبّته على جهازك ليُشغّل ملفات الـ JavaScript. هذا أبسط وصف ممكن، وهو دقيق تماماً. فعندما تكتب الأمر node script.js، تقوم بيئة تشغيل node js بقراءة الملف، ثم تُمرّره إلى محرك V8 التابع لجوجل (نفس محرك JavaScript المستخدم في متصفح Chrome) ليُنفّذه، مع مجموعة ضخمة من الـ APIs الإضافية المُلحقة به للقيام بمهام لا يستطيع V8 إنجازها وحده.

فمحرك V8 يُتقن تنفيذ شيفرة JavaScript، لكنه لا يعرف كيف يفتح ملفاً، ولا كيف يستمع إلى منفذ TCP، ولا كيف يُنشئ عملية (process) جديدة، ولا حتى كيف يقرأ متغيّر بيئة. كل هذه الوظائف يوفّرها Node.js مكتوبةً بلغة C++، ويُتيحها لك داخل شيفرة JavaScript على هيئة وحدات مدمجة جاهزة للاستخدام.

node --version
node script.js

إذًا، Node ليست لغة برمجة، وليست إطار عمل. هي بيئة تشغيل: محرك V8 مضافًا إليه مكتبة قياسية ونظام وحدات وحلقة أحداث. هذا كل ما في الأمر.

أول سكربت لك

أي ملف بامتداد .js يُعتبر برنامج Node صالحًا. لا حاجة لأي قوالب جاهزة، ولا لدالة main:

index.js
Output
Click Run to see the output here.

console.log يشتغل بنفس الطريقة تمامًا كما في المتصفح. قوالب النصوص (Template literals)، كائن Date، المصفوفات، الـ Promises… كل خصائص اللغة التي تعرفها مسبقًا مصدرها محرك V8، وسلوكها واحد لا يتغيّر. ما يختلف فعلًا في Node هو ما يحيط باللغة من أدوات.

المتغيرات العامة الخاصة ببيئة Node

المتصفح يوفّر لك window وdocument وlocalStorage وfetch. أما Node، باعتبارها بيئة تشغيل من جهة الخادم، فلديها مجموعة مختلفة من المتغيرات العامة مصمَّمة لهذا الغرض:

index.js
Output
Click Run to see the output here.
  • process هو الكائن الذي يمثّل عملية Node الجارية حالياً. من خلاله تصل إلى متغيرات البيئة عبر process.env، ووسائط سطر الأوامر عبر process.argv، كما يوفّر لك دوال للخروج من البرنامج مثل process.exit(1).
  • __filename و __dirname يعطيانك المسار المطلق للملف الحالي والمجلد الذي يحويه. (أمّا في وحدات ES Modules فلا وجود لهما، وتستخدم بدلاً منهما import.meta.url.)
  • global هو الكائن الجذري في Node، وهو المكافئ لكائن window في المتصفح.

لن تجد هنا document ولا window. إذا حاولت استخدام أيٍّ منهما فستحصل على ReferenceError، وهذه عادةً أول إشارة تخبرك بأن المكتبة التي بين يديك مكتوبة للمتصفح ولن تعمل في Node كما هي.

قراءة وسائط سطر الأوامر ومتغيرات البيئة في Node

جزء كبير مما يُستخدم Node لأجله — من أدوات سطر الأوامر (CLIs) إلى سكربتات البناء والخوادم — يعتمد على قراءة الوسائط ومتغيرات البيئة. وكلاهما متاح عبر الكائن process:

index.js
Output
Click Run to see the output here.

process.argv عبارة عن مصفوفة: أول عنصرين فيها هما مسار ثنائي Node ومسار السكربت، لذلك تبدأ الوسائط الحقيقية من الفهرس 2. أما process.env فهو كائن عادي يحتوي على متغيرات البيئة، ومن الشائع جدًا قراءة NODE_ENV أو PORT أو مفاتيح الـ API منه.

وحدات Node js المدمجة

تأتي Node مع مكتبة قياسية يمكن الوصول إليها عبر require (نظام CommonJS) أو import (نظام ESM). تبدأ أسماء الوحدات بالبادئة node: للإشارة بوضوح إلى أنها وحدات مدمجة:

index.js
Output
Click Run to see the output here.

الأدوات التي ستستخدمها في أغلب الأحيان:

  • node:fs — للقراءة من الملفات والكتابة إليها. استخدم node:fs/promises إذا أردت النسخة المتوافقة مع async/await.
  • node:path — لدمج مسارات الملفات وتحليلها وحلّها بطريقة تعمل على جميع أنظمة التشغيل.
  • node:http / node:https — لإنشاء خوادم HTTP وإرسال الطلبات.
  • node:url — لتحليل الروابط وبنائها.
  • node:os — للحصول على معلومات عن الجهاز المضيف.
  • node:crypto — للتجزئة (hashing) وتوليد البايتات العشوائية والتشفير.

هذه الوحدات لا تحتاج إلى تثبيت، فهي مرفقة مع Node نفسه. أما أي شيء آخر فستحصل عليه من npm.

حلقة الأحداث في Node باختصار

يُشغّل Node شيفرة JavaScript الخاصة بك على خيط (thread) واحد فقط، ومع ذلك فهو قادر على التعامل مع عدة مهام في الوقت نفسه. السر وراء ذلك هو حلقة الأحداث (event loop). عندما تستدعي عملية غير متزامنة — كقراءة ملف أو طلب HTTP أو مؤقّت — يُسلّم Node تنفيذ هذه العملية إلى نظام التشغيل (أو إلى مجموعة الخيوط الداخلية thread pool) ويستمر في تنفيذ باقي الكود دون انتظار. وحين تنتهي تلك العملية، تُوضع دالة الاستجابة (callback) في طابور، ثم تلتقطها الحلقة بمجرد أن ينتهي الكود الجاري حالياً.

index.js
Output
Click Run to see the output here.

الترتيب الذي سيُطبع هو 1 ثم 4 ثم 2 ثم 3. فالكود المتزامن (synchronous) يُنفَّذ أولًا، ثم المهام الدقيقة (microtasks) أي الوعود (Promises) التي تم حلّها، وبعدها المؤقتات (timers). ولهذا السبب تحديدًا، أي حلقة ثقيلة تستهلك المعالج ستُجمِّد الخادم بالكامل، لأن الكود الخاص بك يعمل على خيط (thread) واحد فقط. التوازي في Node مبني على عمليات الإدخال/الإخراج (I/O)، لا على الحسابات.

خادم HTTP بسيط بأسطر قليلة

ثمرة كل ما سبق أن كتابة خادم ويب يعمل فعلًا لا تحتاج سوى بضعة أسطر:

index.js
Output
Click Run to see the output here.

بدون أي framework، وبدون أي اعتماديات. الدالة createServer تستقبل دالة تُنفَّذ مع كل طلب وارد، أما listen فهي التي تُشغِّل حلقة الأحداث لمعالجة الاتصالات الواردة. التطبيقات الحقيقية تبني فوق هذا باستخدام Express أو Fastify، لكن في العمق تظل تعتمد على نفس الوحدة المدمجة http.

الفرق بين node js والمتصفح

من المفيد أن نوضّح بشكل صريح ما ينتقل بين البيئتين وما لا ينتقل:

يعمل في الاثنينخاص بـ Node فقطخاص بالمتصفح فقط
ميزات اللغة (classes، promises، async/await)fs، http، process، __dirnamewindow، document، DOM
console.logنظام CommonJS عبر require وبعض خصوصيات ESM في NodelocalStorage، sessionStorage
fetch (من Node 18 وما بعده)الوصول إلى نظام الملفات ومقابس الشبكةأحداث المستخدم وعرض الصفحة
setTimeout، setIntervalالعمليات الفرعية والـ streamsHistory API، navigator

النسخ الحديثة من Node تبنّت عدة واجهات برمجية من المتصفح مثل fetch وURL وAbortController وstructuredClone، فأصبحت الفجوة بينهما أضيق مما كانت. لكن DOM لن يصل إلى Node، ونظام الملفات لن يصل إلى المتصفح.

node js vs Deno vs Bun

يبقى Node هو الخيار الافتراضي، لكنه لم يعد بيئة التشغيل الوحيدة لـ JavaScript. هناك Deno وBun كبدائل؛ Deno من المطوّر الأصلي لـ Node نفسه، وBun من فريق أحدث يركّز على السرعة. كلاهما يشغّل JavaScript (وTypeScript بشكل أصلي)، ويأتي بأدوات مدمجة مثل مشغّل الاختبارات والـ bundler، ويختلفان عن Node في طريقة التعامل مع الوحدات والصلاحيات وتنصيب الحزم.

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

تشغيل السكربتات بسرعة

إليك عدة طرق لتنفيذ الكود فعليًا أثناء عملك:

# تشغيل ملف
node script.js

# تشغيل سطر واحد
node -e "console.log(2 ** 10)"

# فتح REPL (موجّه تفاعلي)
node

# مراقبة ملف وإعادة التشغيل عند الحفظ (Node 18.11+)
node --watch script.js

الـREPL مفيد كمسوّدة سريعة لما تحب تختبر شو بترجّع دالة معيّنة من دون ما تنشئ ملف. وخيار --watch عمليّ جداً أثناء التطوير — احفظ الملف، وNode راح يعيد تشغيل السكربت تلقائياً.

التالي: التقاط الأخطاء

تشغيل الكود شيء، والتعامل معه لما يصير في مشكلة شيء ثاني تماماً. قراءة الملفات ممكن تفشل، طلبات HTTP ممكن تنتهي مهلتها، وتحليل JSON ممكن يرمي استثناء. الفصل الجاي راح يتناول try/catch وأنواع الأخطاء والأنماط المستخدمة للتعامل مع الأشياء اللي بتنكسر — ولأنّك في برنامج Node، فكل شي في النهاية بينكسر.

الأسئلة الشائعة

ما هي بيئة تشغيل Node.js؟

Node.js ببساطة هو برنامج يُشغّل JavaScript خارج المتصفح. يجمع بين محرك V8 من Google (نفس المحرك الذي يُشغّل JS داخل Chrome) وطبقة مكتوبة بلغة C++ توفّر واجهات برمجية لا يملكها V8 وحده، مثل الوصول لنظام الملفات والشبكات والعمليات والمؤقتات. هذا المزيج هو ما يسمح لك ببناء خوادم وأدوات سطر أوامر وأدوات بناء باستخدام JavaScript.

ما الفرق بين Node.js والمتصفح؟

كلاهما يُشغّل JavaScript، لكن الواجهات المحيطة باللغة تختلف كليًا. المتصفح يوفّر لك window و document وشجرة DOM، بينما يوفّر Node كائنات مثل process و fs و http و __dirname ونظام تحميل الوحدات عبر CommonJS أو ESM. لا يوجد DOM في Node، ولا يوجد نظام ملفات في المتصفح — اللغة مشتركة، أما المنصة فلا.

هل Node.js إطار عمل أم بيئة تشغيل؟

هو بيئة تشغيل (Runtime) وليس إطار عمل. Node في حد ذاته لا يفرض عليك أي هيكلة للتطبيق، فهو يكتفي بتنفيذ JavaScript وإتاحة الواجهات البرمجية. أما أُطر العمل مثل Express و Next.js و NestJS فهي مبنية فوق Node. كما توجد بيئات تشغيل بديلة مثل Deno و Bun تنافس Node وتؤدي نفس الدور.

ما هي حلقة الأحداث (Event Loop) في Node؟

حلقة الأحداث هي ما يسمح لـ Node بالتعامل مع مهام كثيرة في آنٍ واحد عبر خيط تنفيذ واحد فقط. عند استدعاء عملية غير متزامنة — كقراءة ملف أو طلب HTTP أو setTimeout — يُسلّم Node المهمة لنظام التشغيل ويتابع تنفيذ بقية الكود. وعند انتهاء المهمة، توضع دالة الاستدعاء في طابور الانتظار لتلتقطها حلقة الأحداث. لهذا السبب لا تُوقف fs.readFile تنفيذ برنامجك.

تعلّم البرمجة مع Coddy

ابدأ الآن