كيفية كتابة تطبيق Node and Express جاهز للإنتاج

هيكلة المشروع

عندما بدأت في إنشاء تطبيقات Node & Express ، لم أكن أعرف مدى أهمية هيكلة تطبيقك. لا يأتي Express بقواعد أو إرشادات صارمة للحفاظ على هيكل المشروع.

أنت حر في استخدام أي هيكل تريده. عندما تنمو قاعدة الشفرة الخاصة بك ، ينتهي بك الأمر بالحصول على routeمعالجات طويلة . هذا يجعل من الصعب فهم الكود الخاص بك ويحتوي على أخطاء محتملة.

إذا كنت تعمل من أجل شركة ناشئة ، فلن يكون لديك في معظم الأحيان وقت لكسر مشروعك أو تشكيله. يمكن أن ينتهي بك الأمر مع حلقة لا نهاية لها من إصلاح الأخطاء وإصلاحها.

بمرور الوقت ، أثناء العمل مع كل من الفرق الصغيرة والفرق الكبيرة ، أدركت نوع الهيكل الذي يمكن أن ينمو مع مشروعك ولا يزال من السهل صيانته.

تحكم عرض نموذج

يساعد نمط MVC في التطور السريع والمتوازي. على سبيل المثال ، يمكن لأحد المطورين العمل على العرض ، بينما يمكن لمطور آخر العمل على إنشاء منطق الأعمال في وحدة التحكم.

دعنا نلقي نظرة على مثال بسيط لتطبيق CRUD للمستخدم.

project/ controllers/ users.js util/ plugin.js middlewares/ auth.js models/ user.js routes/ user.js router.js public/ js/ css/ img/ views/ users/ index.jade tests/ users/ create-user-test.js update-user-test.js get-user-test.js .gitignore app.js package.json
  • وحدات التحكم: حدد معالجات مسار التطبيق ومنطق الأعمال
  • الاستخدام : يكتب هنا الوظائف المساعدة / المساعدة والتي يمكن استخدامها من قبل أي وحدات تحكم. على سبيل المثال ، يمكنك كتابة دالة مثل mergeTwoArrays(arr1, arr2).
  • البرامج الوسيطة: يمكنك كتابة البرامج الوسيطة لتفسير جميع الطلبات الواردة قبل الانتقال إلى معالج المسار. فمثلا،

    router.post('/login', auth, controller.login)أين authيتم تعريف دالة البرمجيات الوسيطة في middlewares/auth.js.

  • النماذج: أيضًا نوع من البرامج الوسيطة بين وحدة التحكم وقاعدة البيانات. يمكنك تحديد مخطط وإجراء بعض التحقق من الصحة قبل الكتابة إلى قاعدة البيانات. على سبيل المثال ، يمكنك استخدام ORM مثل Mongoose والتي تأتي مع ميزات وطرق رائعة لاستخدامها في المخطط نفسه
  • المسارات: تحديد مسارات تطبيقك باستخدام طرق HTTP. على سبيل المثال ، يمكنك تحديد كل ما يتعلق بالمستخدم.
router.post('/users/create', controller.create) router.put('/users/:userId', controller.update) router.get('/users', controller.getAll)
  • عام: تخزين الصور الثابتة في /imgملفات جافا سكريبت المخصصة و CSS/css
  • طرق العرض: تحتوي على قوالب ليتم عرضها بواسطة الخادم.
  • الاختبارات: هنا يمكنك كتابة جميع اختبارات الوحدة أو اختبارات القبول لخادم API.
  • app.js: بمثابة الملف الرئيسي للمشروع حيث تقوم بتهيئة التطبيق وعناصر المشروع الأخرى.
  • package.json: يعتني بالتبعيات ، والبرامج النصية المراد تشغيلها باستخدام npmالأمر ، وإصدار مشروعك.

الاستثناءات ومعالجة الخطأ

هذا هو أحد أهم الجوانب التي يجب التفكير فيها عند إنشاء أي مشروع بأي لغة. دعونا نرى كيفية التعامل مع الأخطاء والاستثناءات بأمان في تطبيق Express.

استخدام الوعود

تتمثل إحدى مزايا استخدام الوعود على عمليات الاسترجاعات في إمكانية التعامل مع الاستثناءات / الأخطاء الضمنية أو الصريحة في كتل التعليمات البرمجية غير المتزامنة بالإضافة إلى التعليمات البرمجية المتزامنة المحددة في .then()رد نداء الوعد

فقط أضف .catch(next)في نهاية سلسلة الوعد. فمثلا:

router.post('/create', (req, res, next) => { User.create(req.body) // function to store user data in db .then(result => { // do something with result return result }) .then(user => res.json(user)) .catch(next) })

باستخدام try-catch

محاولة الالتقاط هي طريقة تقليدية لالتقاط الاستثناءات في التعليمات البرمجية غير المتزامنة.

دعنا نلقي نظرة على مثال مع إمكانية الحصول على استثناء:

router.get('/search', (req, res) => { setImmediate(() => { const jsonStr = req.query.params try { const jsonObj = JSON.parse(jsonStr) res.send('Success') } catch (e) { res.status(400).send('Invalid JSON string') } }) })

تجنب استخدام رمز متزامن

يُعرف الرمز المتزامن أيضًا باسم رمز الحظر ، لأنه يمنع التنفيذ حتى يتم تنفيذه.

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

لا تستخدمها في الإنتاج خاصة :)

العديد من وحدات نود.جي إس تأتي مع كل من .syncو .asyncسائل، لذلك استخدام المتزامن في الإنتاج.

ولكن ، إذا كنت لا تزال ترغب في استخدام واجهة برمجة تطبيقات متزامنة ، فاستخدم --trace-sync-ioعلامة سطر الأوامر. سيقوم بطباعة تحذير وتتبع مكدس كلما كان التطبيق الخاص بك يستخدم واجهة برمجة تطبيقات متزامنة.

لمزيد من المعلومات حول أساسيات معالجة الأخطاء ، راجع:

  • معالجة الخطأ في Node.js
  • بناء تطبيقات عقدة قوية: معالجة الأخطاء (مدونة StrongLoop)
ما لا يجب عليك فعله هو الاستماع إلى uncaughtExceptionالحدث ، المنبعث عندما فقاعات استثناء على طول الطريق إلى حلقة الحدث. بشكل عام لا يفضل استخدامه.

التسجيل بشكل صحيح

يعد التسجيل ضروريًا لتصحيح الأخطاء ونشاط التطبيق. يتم استخدامه بشكل أساسي لأغراض التنمية. نحن نستخدم console.logو console.errorلكن هذه هي وظائف متزامن.

لأغراض التصحيح

يمكنك استخدام وحدة نمطية مثل التصحيح. تمكّنك هذه الوحدة من استخدام متغير بيئة DEBUG للتحكم في رسائل التصحيح التي يتم إرسالها console.err()، إن وجدت.

لنشاط التطبيق

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

تحقق من كيفية استخدام المكونات الإضافية mongoose للقيام بمراجعة تطبيقي.

طريقة أخرى هي الكتابة إلى ملف أو استخدام مكتبة تسجيل مثل Winston أو Bunyan. للحصول على مقارنة تفصيلية بين هاتين المكتبتين ، راجع منشور مدونة StrongLoop مقارنة تسجيل Winston و Bunyan Node.js.

تتطلب ("./../../../../../../") فوضى

توجد حلول مختلفة لهذه المشكلة.

إذا وجدت أن أي وحدة أصبحت شائعة وإذا كانت تتمتع باستقلالية منطقية عن التطبيق ، فيمكنك تحويلها إلى وحدة npm خاصة واستخدامها مثل أي وحدة أخرى في package.json.

أو

const path = require('path'); const HOMEDIR = path.join(__dirname,'..','..');

أين __dirname هو المتغير المضمن الذي يسمي الدليل الذي يحتوي على الملف الحالي ..، ..وهو العدد المطلوب من الخطوات لأعلى شجرة الدليل للوصول إلى جذر المشروع.

من هناك ببساطة:

const foo = require(path.join(HOMEDIR,'lib','foo')); const bar = require(path.join(HOMEDIR,'lib','foo','bar'));

لتحميل ملف تعسفي داخل المشروع.

اسمحوا لي أن أعرف في التعليق أدناه إذا كان لديك أفكار أفضل :)

تعيين NODE_ENV على "الإنتاج"

و NODE_ENV يحدد متغير البيئة البيئة التي يعمل تطبيق (عادة أو التطوير أو الإنتاج). من أبسط الأشياء التي يمكنك القيام بها لتحسين الأداء ضبط NODE_ENV"الإنتاج".

تعيين NODE_ENV على " الإنتاج " يجعل Express:

  • قوالب عرض ذاكرة التخزين المؤقت.
  • ذاكرة التخزين المؤقت لملفات CSS التي تم إنشاؤها من امتدادات CSS.
  • إنشاء رسائل خطأ أقل تفصيلاً.

تشير الاختبارات إلى أن مجرد القيام بذلك يمكن أن يحسن أداء التطبيق بثلاثة أضعاف!

باستخدام مدير العمليات

بالنسبة للإنتاج ، يجب ألا تستخدم ببساطة node app.j- إذا تعطل تطبيقك ، فسيكون غير متصل بالإنترنت حتى تعيد تشغيله.

أشهر مديري العمليات في Node هم:

  • StrongLoop Process Manager
  • PM2
  • Forever

I personally use PM2.

For a feature-by-feature comparison of the three process managers, see //strong-pm.io/compare/. For a more detailed introduction to all three, see Process managers for Express apps.

Run your app in a cluster

In a multi-core system, you can increase the performance of a Node app by many times by launching a cluster of processes.

A cluster runs multiple instances of the app, ideally one instance on each CPU core. This distributes the load and tasks among the instances.

Using Node’s cluster module

Clustering is made possible with Node’s cluster module. This enables a master process to spawn worker processes. It distributes incoming connections among the workers.

ومع ذلك ، بدلاً من استخدام هذه الوحدة مباشرةً ، من الأفضل بكثير استخدام إحدى الأدوات العديدة المتوفرة التي تقوم بذلك نيابةً عنك تلقائيًا. على سبيل المثال node-pm أو الكتلة-service.

باستخدام PM2

بالنسبة إلى pm2 ، يمكنك استخدام الكتلة مباشرة من خلال الأمر. فمثلا،

# Start 4 worker processes pm2 start app.js -i 4 # Auto-detect number of available CPUs and start that many worker processes pm2 start app.js -i max 

إذا واجهت أي مشاكل ، فلا تتردد في الاتصال أو التعليق أدناه.

وسأكون سعيدا للمساعدة :)

لا تتردد في التصفيق إذا كنت تعتبر هذا قراءة جديرة بالاهتمام!

المراجع: //expressjs.com/en/advanced/best-practice-performance.html

نُشر في الأصل على 101node.io في 30 سبتمبر 2018.