تُعَدّ Node.js بيئة تشغيل JavaScript التي تعمل من طرف الخادم، وهي مفتوحة المصدر ومتعددة المنصات cross-platform -أي تعمل على أكثر من نظام تشغيل- وهي مبنية على محرك جافاسكربت Chrome V8، وتستعمل أساسيًا لإنشاء خوادم الويب، لكنها ليست محدودةً لهذه المهمة فقط، كما أنها لاقت رواجًا بدءًا من انطلاقها في 2009، وتلعب الآن دورًا مهمًا في عالم تطوير الويب، فإذا عددنا أنّ النجوم التي يحصل عليها المشروع في GitHub معيارًا لشهرة البرمجية، فاعلم أنّ Node.js قد حصدت أكثر من 84 ألفًا من النجوم حتى الآن، ومن الجدير بالذكر أنّ Node.js مبنية على محرك جافاسكربت Chrome V8، كما تُستعمل بصورة أساسية لإنشاء خوادم الويب، لكنها ليست محدودةً لهذه المهمة فقط.
هذا المقال جزء من سلسلة حول Node.js:
- مقدمة إلى Node.js
- استخدام الوضع التفاعلي والتعامل مع سطر الأوامر في Node.js
- دليلك الشامل إلى مدير الحزم npm في Node.js
- كيفية تنفيذ الدوال داخليا ضمن Node.js
- البرمجة غير المتزامنة في Node.js
- التعامل مع الطلبيات الشبكية في Node.js
- التعامل مع الملفات في Node.js
- تعرف على وحدات Node.js الأساسية
أفضل ميزات Node.js
تتميز Node.js بالمزايا التالية:
السرعة
إحدى الميزات التي تشتهر بها Node.js هي السرعة، فشيفرة JavaScript التي تعمل على Node.js اعتمادًا على اختبارات الأداء benchmark يمكن أن تكون بضعفي سرعة تنفيذ اللغات المصرَّفة compiled مثل C أو Java، وأضعاف سرعة اللغات المفسَّرة مثل بايثون أو روبي بسبب نموذج عدم الحجب non-blocking الذي تستعمله.
بسيطة
صدِّقنا عندما نخبرك بأن Node.js بسيطة، بل بسيطة جدًا.
تستعمل JavaScript
تشغِّل Node.js شيفرة JavaScript، وهذا يعني أنّ ملايين مبرمجي الواجهات الأمامية الذين يستعملون JavaScript في المتصفح سيستطيعون العمل على شيفرات من طرف الخادم ومن طرف الواجهات الأمامية باستخدام اللغة نفسها، فلا حاجة إلى تعلّم لغة جديدة كليًا، حيث ستكون جميع التعابير التي تستعملها في JavaScript متاحةً في Node.js، واطمئن إلى أنّ آخر معايير ECMAScript مستعملة في Node.js، فلا حاجة إلى انتظار المستخدِمين ليحدِّثوا متصفحاتهم، فأنت صاحب القرار بأي نسخة ECMAScript تريد استخدامها في برنامجك باختيار إصدار Node.js المناسب.
محرك V8
يمكنك الاستفادة من عمل آلاف المهندسين الذين جعلوا -ويستمروا بجعل- محرك JavaScript الخاص بمتصفح Chrome سريعًا للغاية، وذلك باعتماد Node.js على محرك Chrome V8 المفتوح المصدر.
منصة غير متزامنة
تُعَدّ جميع الأوامر البرمجية في لغات البرمجة التقليدية حاجبة blocking افتراضيًا مثل سي C وجافا Java وبايثون وبي إتش بي PHP إلا إذا تدخّلتَ بصورة صريحة لإنشاء عمليات غير متزامنة؛ فإذا أجريت مثلًا طلبًا شبكيًا لقراءة ملف JSON، فسيتوقف التنفيذ حتى يكون الرد response جاهزًا.
تسمح JavaScript بكتابة شيفرات غير متزامنة asynchronous وغير حاجبة non-blocking بطريقة سهلة جدًا باستخدام خيط thread وحيد ودوال رد النداء callback functions والبرمجة التي تعتمد على الأحداث event-driven، حيث نمرر دالة رد نداء والتي ستُستدعَى حين نتمكن من إكمال معالجة العملية وذلك في كل مرة تحدث عملية تستهلك الموارد، كما أننا لن ننتظر الانتهاء من ذلك قبل الاستمرار في تنفيذ بقية البرنامج.
أُخِذت هذه الآلية من المتصفح، فلا يمكننا انتظار تحميل شيء ما عبر طلب AJAX قبل أن نكون قادرين على التعامل مع أحداث النقر على عناصر الصفحة، فيجب حدوث كل شيء في الوقت الحقيقي لتوفير تجربة جيدة للمستخدِم، مما يسمح بمعالجة آلاف الاتصالات بخادم Node.js وحيد دون الدخول في تعقيدات إدارة الخيوط threads، والتي تكون سببًا رئيسيًا للعلل في البرامج.
اقتباسملاحظة: إذا أنشأتَ المعالج onclick لصفحة الويب، فأنت تستعمل تقنيات البرمجة غير المتزامنة باستخدام معالجات الأحداث في JavaScript.
توفِّر Node.js تعاملًا غير حاجب مع الدخل والخرج I/O، وتكون المكتبات في Node.js عمومًا مكتوبةً بمنهجية عدم الحجب، مما يجعل سلوك الحجب في Node.js استثناءً للقاعدة وليس شيئًا طبيعيًا، كما تكمل Node.js العمليات عند وصول الرد عندما تريد إجراء عملية دخل أو خرج مثل القراءة من الشبكة أو الوصول إلى قاعدة البيانات أو نظام الملفات بدلًا من حجب الخيط blocking the thread وإهدار طاقة المعالج بالانتظار.
عدد هائل من المكتبات
ساعد مدير الحزم npm ببنيته البسيطة النظام العام في node.js، إذ يستضيف npm ما يقرب من 500 ألف حزمة مفتوحة المصدر تستطيع استخدامها بحرّية.
مثال عن تطبيق Node.js
المثال الأكثر شيوعًا عن تطبيق Node.js هو خادم ويب يعرض العبارة الشهيرة Hello World:
const http = require('http') const hostname = '127.0.0.1' const port = 3000 const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('Hello World\n') }) server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`) })
احفظ الشيفرة البسيطة السابقة في ملف باسم server.js ثم نفِّذ node server.js
في الطرفية الخاصة بك وذلك من أجل تنفيذ تلك الشيفرة.
تبدأ الشيفرة السابقة بتضمين وحدة http، إذ تمتلك Node.js مكتبةً قياسيةً رائعةً بما في ذلك دعم التعامل مع الشبكات؛ أما التابع createServer()
الخاص بوحدة http
فيُنشئ خادم HTTP جديد ويعيده، كما أنّ الخادم قد ضُبِط للاستماع إلى منفذ وعنوان شبكي محدَّدين، وعندما يجهز الخادم فستُستدعى دالة رد النداء والتي تخبرنا في هذه الحالة أنّ الخادم جاهز، وكلما استقبل الخادم طلبًا request جديدًا، فسيُطلَق الحدث request الذي يوفِّر كائنين هما الطلب أي كائن http.IncomingMessage
والرد أي كائن http.ServerResponse
، ويُعَدّ هذان الكائنان أساسًا للتعامل مع استدعاء HTTP.
يوفِّر الكائن الأول معلومات الطلبية لكننا لم نستعمله في هذا المثال البسيط، إلا أنه يمكنك الوصول إلى ترويسات الطلب وإلى بيانات الطلب؛ أما الكائن الثاني فيعيد البيانات إلى صاحب الطلب caller، وفي هذه الحالة باستخدامنا للسطر التالي:
res.statusCode = 200
ضبطنا قيمة الخاصية statusCode إلى 200 والتي تعني أنّ الرد ناجح، ثم ضبطنا ترويسة Content-Type كما يلي:
res.setHeader('Content-Type', 'text/plain')
ثم ننهي الطلب بإضافة المحتوى على أساس وسيط argument إلى التابع end()
:
res.end('Hello World\n')
أدوات Node.js وأطر عملها
تُعَدّ Node.js منصةً منخفضة المستوى، كما توجد آلاف المكتبات المكتوبة باستخدام Node.js لتسهيل الأمور على المطوِّرين وجعلها أكثر متعةً وسلاسةً، إذ أصبح عدد كبير من هذه المكتبات شائعًا بين المطوِّرين، وهذه قائمة غير شاملة للمكتبات التي نراها تستحق التعلم:
- Express: أحد أبسط وأقوى الطرق لإنشاء خادم ويب، ويكون تركيزه على البساطة وعدم الانحياز والميزات الأساسية لخادم الويب هو مفتاح نجاحه.
- Meteor: إطار عمل Framework قوي جدًا ومتكامل، يسمح لك ببناء التطبيقات باستخدام JavaScript ومشاركة الشيفرة بين العميل والخادم، كما أصبح الآن يتكامل بسلاسة مع مكتبات واجهة المستخدِم مثل React و Vue و Angular، في حين يمكن استخدامه أيضًا لإنشاء تطبيقات الويب.
- koa: بناه فريق Express نفسه ويطمح إلى أن يكون أصغر وأبسط اعتمادًا على سنوات الخبرة الطويلة للفريق، إذ بدأ هذا المشروع الجديد للحاجة إلى إنشاء تغييرات غير متوافقة مع ما سبقها دون تخريب ما أُنجِز في المشروع.
- Next.js: إطار عمل يستعمل التصيير rendering من طرف الخادم لتطبيقات React.
- Micro: خادم خفيف جدًا لإنشاء خدمات HTTP مصغرة microservices غير متزامنة.
- Socket.io: محرك تواصل في الوقت الحقيقي لبناء تطبيقات الشبكة.
تاريخ موجز عن Node.js
لننظر إلى تاريخ Node.js من عام 2009 حتى الآن.
أُنشِئت لغة JavaScript في شركة Netscape على أساس أداة لتعديل صفحات الويب داخل متصفحها Netscape Navigator، كما يُعَدّ بيع خوادم الويب جزءًا من نموذج الأعمال في Netscape والتي تحتوي على بيئة باسم Netscape LiveWire التي تستطيع إنشاء صفحات آلية باستخدام JavaScript من طرف الخادم؛ أي أنّ فكرة استخدام JavaScript من طرف الخادم لم تبدأ من Node.js وإنما هي قديمة قدم JavaScript، إلا أنها لم تكن ناجحةً في تلك الفترة.
أحد العوامل الرئيسية لاشتهار Node.js هو التوقيت، إذ بدأت لغة JavaScript تُعَدّ لغةً حقيقيةً، وذلك بفضل تطبيقات Web 2.0 التي أظهرت للعالم كيف تكون التجربة الحديثة للويب مثل Google Maps أو GMail، كما أنّ أداء محركات JavaScript قد ارتفع بشدة بفضل حرب المتصفحات، إذ تعمل فرق التطوير خلف كل متصفح رئيسي بجدّ كل يوم لتحسين الأداء، وكان هذا فوزًا عظيمًا لمنصة JavaScript، علمًا أنّ محرك V8 الذي تستعمله Node.js هو محرك متصفح Chrome، وبالطبع لم تكن شهرة Node.js محض صدفة أو توقيت جيد، إذ أضافت مفاهيم ثورية في كيفية البرمجة باستخدام JavaScript من طرف الخادم.
- عام 2009: ولدت Node.js وأُنشِئت أول نسخة من npm.
- عام 2010: ولد كل من Express وSocket.io.
- عام 2011: وصل npm إلى الإصدار 1.0 وبدأت الشركات الكبيرة بتبني Node.js مثل LinkedIn، كما ولد Hapi.
- عام 2012: استمرت عملية تبنّي Node.js بسرعة كبيرة.
- عام 2013: أُنشِئت أول منصة تدوين باستخدام Node.js: ولدت Koa.
- عام 2014: اشتق مشروع IO.js من Node.js بهدف إضافة دعم ES6 والتطوير بوتيرة أسرع.
- عام 2015: أُسست منظمة Node.js Foundation، ودمج مشروع IO.js مع Node.js مجددًا، كما أصبح npm يدعم الوحدات الخاصة private modules، وأُصدرت نسخة Node 4 (ولم تُصدَر النسخة 1 أو 2 أو 3 من قبل).
- عام 2016: ولد مشروع Yarn، وأُصدِرت Node 6.
- عام 2017: ركّز npm على الحماية أكثر، وأُصدرت Node 8، وأضاف محرك V8 وحدة HTTP/2 بنسخة تجريبية.
-
عام 2018: أُصدرت Node 10، وأضيف دعم تجريبي لوحدات ES بلاحقة
.mjs
. - عام 2019: أُصدرت Node 12 وNode 13.
- عام 2020: أُصدرت Node 14.
- عام 2021: الإصدار الحالي هو 16 والذي أصبح الإصدار المستقر طويل الدعم LTS حاليًا.
كيفية تثبيت Node.js
يمكن تثبيت Node.js بطرائق مختلفة، وسنشرح في هذا الفصل أشهر الطرائق وأسهلها لتثبيتها، كما أنّ الحزم الرسمية لجميع أنظمة التشغيل الرئيسية متوافرة على الرابط nodejs.org/en/download.
إحدى الطرائق المناسبة لتثبيت Node.js هي استعمال مدير الحزم، حيث يملك كل نظام تشغيل مدير حزم خاص به، ففي نظام macOS يكون مدير الحزم Homebrew هو مدير الحزم الأساسي، ويسمح بعد تثبيته بتثبيت Node.js بسهولة، وذلك بتنفيذ الأمر التالي في سطر الأوامر داخل الطرفية، ولن نذكر بالتفصيل مدراء الحزم المتاحة للينكس أو ويندوز منعًا للإطالة، لكنها موجودة بالتفصيل في موقع nodejs.org:
brew install node
يُعَدّ nvm
الطريق الشائع لتشغيل Node.js، إذ يسمح لك بتبديل إصدار Node.js بسهولة وتثبيت الإصدارات الجديدة لتجربتها ثم العودة إلى الإصدار القديم إذا لم يعمل كل شيء على ما يرام، فمن المفيد جدًا على سبيل المثال تجربة الشيفرة الخاصة ببرنامج على الإصدارات القديمة من Node.js، كما ننصحك بمراجعة github.com/creationix/nvm لمزيد من المعلومات حول هذا الخيار، وننصحك بصورة شخصية باستعمال المثبِّت الرسمي إذا أنت حديث العهد على Node.js ولا تريد استخدام مدير الحزم الخاص بنظام تشغيلك، لكن على أي حال، سيكون البرنامج التنفيذي node متاحًا في سطر الأوامر بعد تثبيت Node.js بأي طريقة من الطرائق السابقة.
ماذا عليك معرفته في JavaScript لاستخدام Node.js
إذا بدأت لتوّك مع JavaScript، فما مدى عمق المعلومات التي تلزمك لاستخدام Node.js؟ من الصعب الوصول إلى النقطة التي تكون فيها واثقًا من قدراتك البرمجية كفاية، فحين تعلّمك كتابة الشيفرات، فقد تكون محتارًا متى تنتهي شيفرة JavaScript ومتى تبدأ Node.js وبالعكس، لذا ننصحك أن تكون متمكنًا تمكنًا جيدًا من المفاهيم الأساسية في JavaScript قبل التعمق في Node.js:
- بنية البرنامج.
- التعابير.
- الأنواع.
- المتغيرات
- الدوال والدوال السهمية.
-
الكلمة المحجوزة
this
. - حلقات التكرار والمجالات scopes.
- المصفوفات.
- الفواصل المنقوطة (نعم، هذا المحرف ; ? )
- الوضع الصارم.
- إصدارات ECMAScript مثل ES6 وES2016 وES2017.
ستكون بعد تعلّمك للمفاهيم السابقة في طريقك لتصبح مطور JavaScript محترف في بيئة المتصفح وNode.js، وفيما يلي مفاهيم أساسية لفهم البرمجة غير المتزامنة asynchronous programming والتي هي جزء أساسي من Node.js:
- مفهوم البرمجة غير المتزامنة ورد النداء callbacks.
- المؤقتات Timers.
- الوعود Promises.
- الكلمتان المحجوزتان Async وAwait.
- التعابير المغلقة Closures.
- حلقات الأحداث.
توجد مقالات كثيرة وكتب في أكاديمية حسوب بالإضافة إلى توثيق JavaScript في موسوعة حسوب عن جميع المواضيع السابقة.
الاختلافات بين Node.js والمتصفح
كيف تختلف كتابة تطبيقات JavaScript في Node.js عن البرمجة للويب داخل المتصفح؟ يستخدِم كل من المتصفح وNode.js لغة JavaScript للبرمجة؛ لكن بناء التطبيقات التي تعمل في المتصفح مختلف تمامًا عن بناء تطبيقات Node.js، فعلى الرغم من أنهما يستعملان لغة البرمجة نفسها JavaScript، إلا أنه هنالك اختلافات جوهرية تجعل الفرق بينهما كبيرًا،.
يملك مطور واجهات المستخدِم الذي يكتب تطبيقات Node.js ميزةً رائعةً ألا وهي استخدامه للغة البرمجة نفسها، فمن المعروف أنه من الصعب تعلّم لغة برمجة جديدة بإتقان، لكن باستعمال لغة البرمجة نفسها لإجراء كل العمل على موقع الويب سواءً للواجهة الأمامية أو الخادم، حيث توجد أفضلية واضحة في هذه النقطة؛ إلا أنّ بيئة العمل هي التي تختلف.
ستتعامل أغلب الوقت في المتصفح مع شجرة DOM أو غيرها من الواجهات البرمجية الخاصة بالمتصفح Web Platform APIs مثل ملفات الارتباط Cookies والتي لا توجد في Node.js، وبالطبع لن تكون الكائنات document
وwindow
وغيرها من كائنات المتصفح متوافرةً، كما لن نحصل على الواجهات البرمجية APIs التي توفرها Node.js عبر وحداتها مثل الوصول إلى نظام الملفات.
يوجد اختلاف كبير آخر وهو أنك تستطيع التحكم في البيئة التي تعمل فيها Node.js ما لم تبني تطبيقًا مفتوح المصدر يمكن لأي شخص نشره في أيّ مكان، فأنت تعلم ما هي نسخة Node.js التي سيعمل عليها تطبيقك؛ فليس لديك الحرية في اختيار المتصفح الذي يستخدمه زوار موقعك بموازنة ذلك مع بيئة المتصفح، وهذا يعني أنك يمكنك أن تكتب شيفرات ES6-7-8-9 التي تدعمها نسخة Node.js عندك.
ستكون ملزمًا باستخدام إصدارات JavaScript/ECMAScript القديمة على الرغم من تطوّر JavaScript بسرعة كبيرة، وذلك لأن المتصفحات أبطأ منها والمستخدِمون أبطأ بالتحديث، وصحيحٌ أنك تستطيع استخدام Babel لتحويل شيفرتك إلى نسخة موافقة لمعيار ECMAScript 5 قبل إرسالها إلى زوار موقعك، لكنك لن تحتاج إلى ذلك في Node.js.
يوجد اختلاف آخر هو استخدام Node.js لنظام الوحدات CommonJS، بينما بدأنا نرى أنّ المتصفحات تستخدم معيار وحدات ES Modules؛ وهذا يعني عمليًا أنه عليك استخدام require()
في Node.js، وimport
في المتصفح حاليًا.
محرك V8
V8 هو اسم محرك JavaScript الذي يُشغِّل متصفح Chrome، حيث يأخذ شيفرات JavaScript وينفذها أثناء التصفح عبر Chrome، إذ يوفر بيئة التشغيل اللازمة لتنفيذ شيفرات JavaScript، في حين يوفِّر المتصفح شجرة DOM وغيرها من الواجهات البرمجية للويب، كما يُعَدّ استقلال محرك JavaScript عن المتصفح الذي يستخدمه الميزة الرئيسية التي سببت بانتشار Node.js.
اختار مجتمع مطوري Node.js محرك V8 في 2009، وبعد أن ذاع صيت Node.js صار محرك V8 هو المحرك الذي يشغِّل عددًا غير محصور من شيفرات JavaScript التي تعمل من طرف الخادم، وخذ بالحسبان أنّ بيئة تشغيل Node.js كبيرة جدًا ويعود الفضل إليها في أنّ محرك V8 أصبح يشغِّل تطبيقات سطح المكتب عن طريق مشاريع مثل Electron.js.
محركات JavaScript الأخرى
تملك المتصفحات الأخرى محركات JavaScript مختلفة منها:
- يملك متصفح Firefox محرك SpiderMonkey.
- يملك متصفح Safari محرك JavaScriptCore ويسمى Nitro أيضًا.
- يملك متصفح Edge محرك Chakra.
تطبِّق جميع هذه المحركات معيار ECMA ES-262 والذي يسمى ECMAScript أيضًا، وهو المعيار المستخدَم في لغة JavaScript.
السعي إلى الأداء الأفضل
كُتِب محرك V8 بلغة C++ ويُحسَّن باستمرار، وهو محمول portable ويعمل على ماك ولينكس وويندوز وغيرها من أنظمة التشغيل، كما لن نخوض في تفاصيل محرك V8 لأنها موجودة في مواقع كثيرة مثل موقع V8 الرسمي وتتغير مع مرور الوقت، وعادةً تكون التغييرات كبيرةً، إذ يتطور محرك V8 دومًا كما في غيره في محركات JavaScript لتسريع الويب وبيئة Node.js، كما يجري سباق في عالم الويب للأداء الأفضل منذ سنوات، ونحن -المستخدِمون والمطوِّرون- نستفيد كثيرًا من هذه المنافسة لأنها تعطينا أداءً أسرع وأفضل سنةً بعد سنة.
التصريف Compilation
تُعَدّ لغة JavaScript عمومًا لغةً مفسَّرةً interpreted؛ لكن محركات JavaScript الحديثة لم تَعُد تفسِّر شيفرات JavaScript وحسب، وإنما تُصرِّفها compile، فقد حدث ذلك منذ عام 2009، عندما أُضيف مُصرِّف SpuderMonkey إلى متصفح Firefox 3.5، ثم اتبع الجميع هذه الفكرة، حيث تُصرَّف JavaScript داخليًا في V8 حين اللزوم بتصريف JIT (اختصارًا لـ just-in-time) لتسريع عملية التنفيذ.
قد ترى أنّ ذلك مناف للمنطق، لكن تطورت لغة JavaScript من لغة تنفِّذ عادةً بضعة مئات من الأسطر إلى لغة تشغِّل تطبيقات كاملة تحتوي على آلاف أو حتى مئات الآلاف من الأسطر البرمجية التي تعمل في المتصفح وذلك منذ إطلاق Google Maps في 2004، فيمكن لتطبيقاتنا الآن أن تعمل لساعات في المتصفح بدلًا من سكربتات بسيطة للتحقق من صحة المدخلات أو إجراء أفعال بسيطة معينة، ففي هذا العالم الجديد أصبح من المنطقي تمامًا تصريف شيفرات JavaScript؛ وصحيحٌ أنها قد تأخذ بعض الوقت القليل لجهوزية شيفرة JavaScript، إلا أننا سنرى أداءً أفضل من الشيفرة المفسَّرة فقط.
تشغيل تطبيق Node.js والخروج منه
الطريقة التقليدية لتشغيل برنامج Node.js هي استخدام الأمر node
المتاح في نظام التشغيل بعد تثبيت Node.js ثم تمرير اسم الملف الذي تريد تنفيذه إلى الأمر، فلو كان تطبيق Node.js عندك موجود في ملف باسم app.js
، فيمكنك تشغيله بكتابة الأمر التالي في سطر الأوامر:
node app.js
لنتعلم كيف يمكننا إنهاء تطبيق Node.js بأفضل الطرائق الممكنة، حيث توجد عدة طرق لإنهائه، فعندما تشغِّل برنامج في سطر الأوامر، يمكنك أن توقفه بالضغط على Ctrl+c
، لكن ما نريد الحديث عنه هو إنهاء التطبيق برمجيًا، ولنبدأ بأكثر طريقة قاسية لإنهاء التطبيق، ولنرَ لماذا لا يفترض بك استعمالها.
توفِّر الوحدة الأساسية core module المسماة process
تابعًا يسمح لك بالخروج برمجيًا من تطبيق Node.js وهو process.exit()
، إذ سيؤدي تشغيل Node.js هذا السطر إلى إغلاق العملية process مباشرةً، وهذا يعني أنه سيتوقف أيّ رد نداء معلَّق، أو أيّ طلب شبكي لا يزال مُرسَلًا، أو أيّ وصول إلى نظام ملفات، أو عمليات تكتب إلى مجرى الخرج القياسي stdout
أو الخطأ القياسي stderr
توقفًا مباشرًا دون سابق إنذار، وإذا لم تجد حرجًا في ذلك، فيمكنك تمرير عدد صحيح إلى التابع ليخبر نظام التشغيل ما هي حالة الخروج exit code:
process.exit(1)
تكون حالة الخروج الافتراضية هي 0، والتي تعني نجاح تنفيذ البرنامج، حيث تمتلك حالات الخروج المختلفة معانٍ خاصة والتي يمكنك استخدامها في نظامك للتواصل مع بقية البرامج، كما يمكنك أيضًا ضبط قيمة الخاصية process.exitCode
بحيث تُعيد Node.js حالة الخروج المضبوطة إلى هذه الخاصية عند انتهاء تنفيذ البرنامج:
process.exitCode = 1
ينتهي البرنامج بسلام عند انتهاء تنفيذ جميع الشيفرات فيه في الحالة الطبيعية، وكثيرًا ما نُنشِئ خوادم باستخدام Node.js مثل خادم HTTP التالي:
const express = require('express') const app = express() app.get('/', (req, res) => { res.send('Hi!') }) app.listen(3000, () => console.log('Server ready'))
لن ينتهي هذا البرنامج أبدًا، فإذا استدعيت التابع process.exit()
، فستنتهي جميع الطلبيات قيد التنفيذ أو المعلَّقة، وهذا ليس أمرًا جميلًا صدقًا، حيث ستحتاج في هذه الحالة إلى إرسال الإشارة SIGTERM إلى الأمر، وسنتعامل مع الأمر باستخدام معالج إشارة العملية process signal handler.
اقتباسملاحظة: لا حاجة إلى تضمين الوحدة
process
باستخدام require، فهي متاحة تلقائيًا.
const express = require('express') const app = express() app.get('/', (req, res) => { res.send('Hi!') }) app.listen(3000, () => console.log('Server ready')) process.on('SIGTERM', () => { app.close(() => { console.log('Process terminated') }) })
قد تتساءل ما هي الإشارات؟ الإشارات هي نظام تواصل داخلي في معيار POSIX، وهو إشعار يُرسَل إلى العملية لإخبارها أنّ حدثًا ما قد حدث، فالإشارة SIGKILL
هي الإشارة التي تخبر العملية بالتوقف عن العمل فورًا، وهي تعمل مثل process.exit()
؛ أما الإشارة SIGTERM
فهي الإشارة التي تخبر العملية بأن تنتهي بلطف، وهي الإشارة التي تُرسَل من مدراء العمليات في أنظمة التشغيل، كما يمكنك إرسال هذه الإشارة من داخل البرنامج باستخدام دالة تابع آخر:
process.kill(process.pid, 'SIGTERM')
أو من برنامج Node.js آخر، أو من أيّ برنامج يعمل على النظام يعرف مُعرِّف العملية PID الخاص بالعملية التي تريد إنهاءها.
متغيرات البيئة: الفرق بين التطوير والإنتاج
متغير البيئة هو اصطلاح مُستخدَم على نطاق واسع في المكتبات الخارجية أيضًا، وسنتعلم كيفية قراءة واستخدام متغيرات البيئة في برنامج Node.js، حيث توفِّر الوحدة الأساسية process
في Node.js الخاصية env
التي تحتوي على جميع متغيرات البيئة المضبوطة في لحظة تشغيل العملية، وفيما يلي مثال يصل إلى متغير البيئة NODE_ENV
المضبوط إلى القيمة development افتراضيًا:
process.env.NODE_ENV // "development"
ضبطه إلى القيمة production قبل تشغيل السكربت سيخبر Node.js أنّ هذه بيئة إنتاجية وليست تطويرية، كما يمكنك بالطريقة نفسها الوصول إلى أيّ متغيرات بيئة خاصة تضبطها.
يمكن أن يكون لديك إعدادات مختلفة لبيئات الإنتاج والتطوير، حيث يفترض Node أنه يعمل دائمًا في بيئة تطوير، ولكن يمكنك إعلام Node.js بأنك تعمل في بيئة إنتاج من خلال ضبط متغير البيئة NODE_ENV=production
عن طريق تنفيذ الأمر التالي:
export NODE_ENV=production
لكن يُفضَّل في الصدَفة shell وضعه في ملف إعداد الصدَفة مثل .bash_profile
مع صدفة Bash، وذلك لأن الإعداد بخلاف ذلك لا يستمر في حالة إعادة تشغيل النظام، كما يمكنك تطبيق متغير البيئة عن طريق وضعه في بداية أمر تهيئة تطبيقك كما يلي:
NODE_ENV=production node app.js
يضمن ضبط البيئة على القيمة production
ما يلي:
- الاحتفاظ بتسجيل الدخول إلى المستوى الأدنى الأساسي.
- إجراء مزيد من مستويات التخبئة أو التخزين المؤقت caching لتحسين الأداء.
تطبِّق مكتبة القوالب Pug التي يستخدمها إطار عمل Express على سبيل المثال عملية التصريف في وضع تنقيح الأخطاء، إذا لم يُضبَط المتغير NODE_ENV
على القيمة production
، حيث تُصرَّف عروض Express في كل طلب في وضع التطوير، بينما تُخزَّن مؤقتًا في وضع الإنتاج، كما يوفِّر إطار Express خطّافات إعداد configuration hooks خاصة بالبيئة تُستدعَى تلقائيًا بناءً على قيمة المتغير NODE_ENV
:
app.configure('development', () => { //... }) app.configure('production', () => { //... }) app.configure('production', 'staging', () => { //... })
يمكنك استخدام ذلك مثلًا لضبط معالجات أخطاء مختلفة في وضع مختلف كما يلي:
app.configure('development', () => { app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }) app.configure('production', () => { app.use(express.errorHandler()) })
استضافة مشاريع Node.js
يمكن استضافة تطبيقات Node.js في أماكن عديدة اعتمادًا على احتياجاتك، وسنذكر لك قائمةً بالخيارات المتاحة أمامك، وهي قائمة غير شاملة بالخيارات التي يمكنك استخدامها لنشر تطبيقك وجعله متاحًا للعامة، وسنرتِّبها من الأبسط والأقل مزايا إلى الأعقد والأقوى:
- أسهل الخيارات على الإطلاق: نفق محلي local tunnel.
- نشر التطبيقات دون أي ضبط.
- Glitch.
- Codepen.
- الخيارات عديمة الخوادم Serverless.
- المنصة على أساس خدمة PAAS.
- Zeit Now.
- Nanobox.
- Heroku.
- Microsoft Azure.
- Google Cloud Platform.
- خادم خاص افتراضي Virtual Private Server أي VPS.
- خادم حقيقي Bare metal.
نفق محلي
يمكنك نشر تطبيقك وتُخديم الطلبات من حاسوبك باستخدام نفق محلي local tunnel حتى إذا كان لديك عنوان IP ديناميكي، أو كنت تحت NAT، فهذا الخيار مناسب لإجراء بعض الاختبارات السريعة، أو تجربة المنتج أو مشاركة التطبيق مع مجموعة صغيرة من الأشخاص، وهنالك أداة رائعة لذلك متاحة لجميع المنصات اسمها ngrok، فكل ما عليك فعله لاستعمالها هو كتابة ngrok PORT
، إذ إنَّ PORT هو المنفذ الذي تريد نشره على الإنترنت، وستحصل على نطاق من ngrok.io، لكن سيسمح لك الاشتراك المدفوع بالحصول على عنوان URL مخصص إضافةً إلى خيارات حماية إضافة (تذكَّر أنك تفتح جهازك إلى الإنترنت)، وهنالك خدمة أخرى يمكنك استخدامها وهي github.com/localtunnel/localtunnel.
نشر التطبيقات دون أي ضبط
هناك خيارات متاحة لنشر تطبيقات Node.js دون أيّ ضبط يُذكر، وسنذكر من هذه الخيارات منصة Glitch ومنصة Codepen.
Glitch
يُعَدّ Glitch بيئةً تسمح لك ببناء تطبيقاتك بسرعة كبيرة، ورؤيتها حيةً على النطاق الفرعي الخاص بك على glitch.com، فلا يمكنك حاليًا الحصول على نطاق مخصص وهنالك بعض المحدوديات، لكن ستبقى مع ذلك بيئةً رائعةً؛ فهي تحتوي على كامل ميزات Node.js وCDN ومكان تخزين آمن للمعلومات الحساسة، بالإضافة إلى الاستيراد والتصدير من GitHub، كما أنّ هذه الخدمة موفَّرة من الشركة التي تقف خلف FogBugz وTrello والمشاركين في إنشاء StackOverflow.
Codepen
منصة Codepen رائعة، فهي تسمح لك بإنشاء مشروع متعدد الملفات ونشره بنطاق مخصص.
الخيارات عديمة الخوادم Serverless
إحدى الطرائق لنشر تطبيقك وعدم الحاجة إلى خادم لإدارته هي استخدام إحدى الخيارات عديمة الخوادم Serverless التي هي منهجية لنشر تطبيقاتك على أساس وظائف functions، وهي ترد على نقطة نهاية شبكية network endpoint، وهذا يسمى أيضًا FAAS أي الوظيفة على أساس خدمة Function As A Service، ومن الخيارات الشائعة جدًا هي:
يوفِّر كلا الخيارين طبقة تجريدية abstraction layer لنشر التطبيقات على حلول مثل AWS Lambda وغيرها من حلول FAAS المبنية على Azure أو Google Cloud.
المنصة على أساس خدمة PAAS
تُعَدّ PASS اختصارًا لـ Platform AS A Service أي المنصة على أساس خدمة، وتحمل عنك هذه المنصات عناء التفكير في كثير من الأمور عند نشر تطبيقك.
Zeit Now
يُعَدّ Zeit خيارًا مثيرًا للاهتمام، فعندما تكتب الأمر now
في الطرفية، فسيتولى أمر نشر تطبيقك كله؛ وهنالك نسخة مجانية مع محدوديات ونسخة مدفوعة بميزات أكثر، حيث ستنسى أنّ هنالك خادم وكل ما عليك فعله هو نشر التطبيق.
Nanobox
سنحيلك إلى موقع Nanobox لتأخذ فكرةً عنه nanobox.io.
Heroku
يُعَدّ Heroku منصةً رائعةً، وهنالك سلسلة فيديوهات عن كيفية نشر التطبيقات عبر Heroku منها فيديو نشر تطبيق React.js ذو واجهات خلفية Node.js على منصة Heroku.
Microsoft Azure
خدمة Azure توفرها Microsoft Cloud، وهنالك مقالة أجنبية تفصيلية عن إنشاء تطبيق Node.js في Azure.
Google Cloud Platform
تُعَدّ منصة Google Cloud خيارًا رائعًا لتنظيم تطبيقاتك، ولديهم توثيق جيد عن Node.js.
خادم خاص افتراضي VPS
ستجد في هذا القسم الخيارات الشائعة التي قد تعرفها من قبل، وهي مرتبة من أكثرها سهولةً للمستخدِم:
- DigitalOcean
- Linode
- Amazon Web Services، ونذكر خصوصًا خدمة Amazon Elastic Beanstalk فهي تسهل بعضًا من تعقيدات AWS.
ولمّا كانت هذه الخدمات توفِّر لك خادم لينكس فارغ يمكنك العمل عليه، فلن نوصي بمقالةٍ أو دليلٍ محدد لهذه الخدمات؛ وهذه ليست جميع الشركات التي توفر خدمات VPS، لكنها هي التي استعملناها سابقًا وننصح بها.
خادم حقيقي
يوجد خيار آخر هو خادم حقيقي bare metal، بحيث تثبت عليه توزيعة لينكس وتصله بالإنترنت أو يمكنك استئجار واحد شهريًا، كما في خدمة Vultr Bare Metal.
ترجمة -وبتصرّف- للفصلين Introduction و Basics من كتاب The Node.js handbook لصاحبه Flavio Copes.
اقرأ أيضًا
- المقال التالي: استخدام الوضع التفاعلي والتعامل مع سطر الأوامر في Node.js
- بناء تطبيق Node.js باستخدام Docker
- إعداد تطبيق node.js لسير عمل يعتمد على الحاويات باستخدام Docker Compose
- تأمين تطبيق Node.js يعمل على الحاويات باستخدام Nginx و Let’s Encrypt و Compose Docker
- نشر تطبيق Node.js على الويب: خدمة هيروكو (Heroku) مثالًا
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.