اذهب إلى المحتوى

يشرح هذا المقال ما ستتعلمه لبناء موقع ويب باستخدام إطار عمل Express، ويوفر نظرةً عامة على مثال موقع المكتبة المحلية الذي سنعمل عليه ونطوّره في المقالات اللاحقة، وسنوضّح كيفية إنشاء مشروع موقع ويب هيكلي يمكنك ملؤه لاحقًا بالوجهات Routes والعروض Views أوالقوالب Templates واستدعاءات قاعدة البيانات الخاصة بالموقع.

  • المتطلبات الأساسية: قراءة مدخل إلى إطار عمل Express،وإعداد بيئة تطوير Node مع Express.
  • الهدف: مقدمة إلى التطبيق العملي الذي سنبنيه في المقالات اللاحقة، وفهم الموضوعات التي سنتناولها، والقدرة على بدء مشاريعك لمواقع الويب الجديدة باستخدام مولّد تطبيقات Express.

سنطور موقع ويب يمكن استخدامه لإدارة دليلٍ لمكتبة محلية، وسنتعلم في هذه السلسلة من المقالات ما يلي:

  • استخدام أداة مولّد تطبيقات Express لإنشاء موقع ويب وتطبيق هيكلي.
  • بدء وإيقاف خادم ويب Node.
  • استخدم قاعدة بيانات لتخزين بيانات تطبيقك.
  • إنشاء الوجهات لطلب معلومات مختلفة، وقوالب أو عروض لعرض البيانات بتنسيق HTML لعرضها في المتصفح.
  • العمل مع الاستمارات Forms.
  • نشر تطبيقك في بيئة الإنتاج.

تعلّمت مسبقًا عن بعض هذه الموضوعات، وتعرّفت إلى بعضها الآخر بإيجاز، ولكن يجب أن تعرف ما يكفي لتطوير تطبيقات Express بنفسك في نهاية هذه السلسلة من المقالات المتفرعة من سلسلة تعلم تطوير الويب.

موقع المكتبة المحلية LocalLibrary

LocalLibrary هو اسم موقع الويب الذي سننشئه ونطوّره في المقالات اللاحقة، والغرض الأساسي من هذا الموقع هو توفير دليل Catalog عبر الإنترنت لمكتبة محلية صغيرة، حيث يمكن للمستخدمين تصفح الكتب المتاحة وإدارة حساباتهم.

اختير هذا المثال بعناية لأنه يمكن تغيير حجمه لإظهار الكثير أو القليل من التفاصيل التي نحتاجها، ويمكن استخدامه لإظهار أي ميزة من ميزات Express تقريبًا، ويسمح بتوفير مسار إرشادي عبر الوظائف التي ستحتاجها في أيّ موقع ويب كما يلي:

  • سنعرّف في المقالات الأولى مكتبةً بسيطةً للتصفح فقط، إذ يمكن لأعضاء المكتبة استخدامها لمعرفة الكتب المتاحة، مما يتيح استكشاف العمليات المشتركة لكل مواقع الويب تقريبًا، وهي قراءة المحتوى وعرضه من قاعدة بيانات.
  • يتوسّع مثال المكتبة في المقالات اللاحقة لإظهار ميزات موقع الويب الأكثر تقدمًا، فمثلًا يمكننا توسيع المكتبة للسماح بإنشاء كتب جديدة، واستخدام ذلك لتوضيح كيفية استخدام الاستمارات ودعم استيثاق Authentication المستخدمين.

سُمِّي هذا المثال بمكتبة محلية لسببٍ ما بالرغم من أنه قابل جدًا للتوسّع، فهدفنا هو إظهار الحد الأدنى من المعلومات التي ستساعدك على بدء استخدام إطار عمل Express وتشغيله بسرعة، لذا سنخزّن معلومات عن الكتب ونسخها والمؤلفين والمعلومات الأساسية الأخرى، ولكن لن نخزّن معلومات حول العناصر الأخرى التي يمكن أن تعيرها المكتبة ولن نوفر البنية الأساسية اللازمة لدعم مواقع مكتبات متعددة أو ميزات مكتبة كبيرة أخرى.

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

إذا واجهتك مشكلة، فيمكنك العثور على النسخة المُطوَّرة بالكامل من موقع الويب على GitHub.

ملاحظة: توجد قائمة بالنسخ المحددة من Node و Express والوحدات الأخرى التي جرى اختبار هذه السلسلة من المقالات على أساسها في الملف package.json الخاص بالمشروع.

حان الوقت لبدء إنشاء مشروع هيكلي بعد أن تعرّفت على موقع المكتبة المحلية LocalLibrary وما ستتعلمه في هذه السلسلة من المقالات.

إنشاء موقع ويب هيكلي

سنوضح الآن كيفية إنشاء موقع ويب هيكلي باستخدام أداة مولّد تطبيقات Express، والتي يمكنك بعد ذلك ملؤها بالوجهات والعروض أو القوالب واستدعاءات قاعدة البيانات الخاصة بالموقع، إذ سنستخدم هذه الأداة لإنشاء إطار عمل لموقع المكتبة المحلية الذي سنضيف إليه لاحقًا جميع الشيفرات البرمجية الأخرى التي يحتاجها الموقع. تُعَد هذه العملية بسيطة جدًا، وتتطلب فقط استدعاء المولّد في سطر الأوامر باسم مشروع جديد، وتحديد محرّك قوالب الموقع ومولد شيفرة CSS اختياريًا.

توضّح الأقسام التالية كيفية استدعاء مولّد التطبيق، وتوفّر شرحًا بسيطًا حول خيارات العرض أو شيفرة CSS المختلفة، وسنشرح كيفية بناء موقع الويب الهيكلي، وسنوضح كيفية تشغيل موقع الويب للتحقق من أنه يعمل بنجاح.

ملاحظة:

  • لا يُعَد مولّد تطبيقات Express المولّد الوحيد لتطبيقات Express، ولا يُعَد المشروع المُولَّد الطريقة الوحيدة القابلة للتطبيق لبناء هيكيلية ملفاتك ومجلداتك، ولكن يحتوي الموقع المُولَّد على بنية معيارية يسهل توسيعها وفهمها. اطلع على مثال Hello world في توثيق Express لمزيد من المعلومات حول الحد الأدنى من تطبيقات Express.
  • يصرّح مولّد تطبيقات Express عن معظم المتغيرات باستخدام var، ولكننا غيّرنا معظمها إلى const، وعددًا قليلًا منها إلى let، لأننا نريد عرض ممارسات جافا سكريبت Javascript الحديثة.
  • يستخدم هذا المقال نسخة Express والاعتماديات الأخرى المُعرَّفة في الملف package.json التي أنشأها مولّد تطبيقات Express، إذ ليست بالضرورة أن تكون النسخة الأحدث، وقد ترغب في تحديثها عند نشر تطبيق حقيقي في بيئة الإنتاج.

استخدام مولد التطبيق

لا بد أنك ثبّتَ المولّد أثناء إعداد بيئة تطوير Node مع Express، ولكن يمكنك تثبيت أداة المولّد على مستوى الموقع باستخدام مدير حزم npm كما يلي:

npm install express-generator -g

يحتوي المولّد على عدد من الخيارات التي يمكنك عرضها في سطر الأوامر باستخدام الأمر ‎--help (أو ‎-h?

> express --help

    Usage: express [options] [dir]

  Options:

        --version        output the version number
    -e, --ejs            add ejs engine support
        --pug            add pug engine support
        --hbs            add handlebars engine support
    -H, --hogan          add hogan.js engine support
    -v, --view <engine>  add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
        --no-view        use static html instead of view engine
    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain CSS)
        --git            add .gitignore
    -f, --force          force on non-empty directory
    -h, --help           output usage information

يمكنك استخدام الأمر express لإنشاء مشروع ضمن المجلد الحالي باستخدام محرّك العروض Jade وشيفرة CSS، وإذا حدّدتَ اسم مجلد، فسيُنشَأ المشروع في مجلد فرعي بهذا الاسم.

express

يمكنك أيضًا اختيار محرك عروض أو قوالب باستخدام ‎--view و/أو محرّك توليد شيفرة CSS باستخدام ‎--css.

ملاحظة: أهملنا الخيارات الأخرى لاختيار محركات القوالب مثل ‎--hogan و ‎--ejs و ‎--hbs وغيرها، لذا استخدم الخيار ‎--view أو ‎-v

محرك العروض الواجب استخدامه

يتيح مولّد تطبيقات Express ضبطَ عددٍ من محرّكات العروض أو القوالب الشائعة، بما في ذلك EJS و Hbs و Pug (أو Jade) و Twig و Vash، ويختار Jade افتراضيًا إن لم تحدد خيار العرض، ويمكن أن يدعم Express أيضًا عددًا كبيرًا من لغات القوالب الأخرى.

ملاحظة: إذا أردتَ استخدام محرك قوالب لا يدعمه المولّد، فاطلع على استخدام محركات القوالب مع Express في توثيق Express وتوثيق محرك العروض الذي تريد استخدامه.

يجب تحديد محرّك القوالب الذي يوفّر جميع الوظائف التي تحتاجها ويسمح لك بالحصول على نتائج في أقرب وقت أو -بعبارة أخرى- باستخدام الطريقة نفسها التي تختار بها أي مكون آخر. إليك بعض الأشياء التي يجب مراعاتها عند الموازنة بين محركات القوالب:

  • الوقت المستغرق للحصول على نتائج: إذا كان فريقك خبيرًا في استخدام لغة القوالب، فيُحتمَل أن يكونوا منتجين بصورة أسرع باستخدام تلك اللغة. إن لم يكن الأمر كذلك، فيجب التفكير في منحنى التعلّم النسبي لمحركات القوالب المُرشَّحة للاستخدام.
  • الشعبية والنشاط: راجع شعبية المحرّك وما إذا كان لديه مجتمع نشط، فمن المهم أن تكون قادرًا على الحصول على الدعم عند ظهور مشاكل طوال مدة عمل الموقع.
  • التنسيق: تستخدم بعض محركات القوالب شيفرة HTML التوصيفية للإشارة إلى المحتوى المُدخَل إلى شيفرة HTML عادية، بينما تبني محركات القوالب الأخرى شيفرة HTML باستخدام صيغة مختلفة (مثل استخدام المسافة البادئة وأسماء الكتل).
  • الأداء أو الوقت اللازم للتقديم rendering time.
  • الميزات: يجب أن تفكر فيما إذا كانت هذه المحركات توفّر الميزات التالية:
    • توريث التخطيط Layout: يسمح بتعريف قالب أساسي ثم يمكنك وراثة أجزاء منه فقط وهي الأجزاء التي تريد أن تكون مختلفة لصفحة معينة، ويُعَد ذلك أسلوبًا أفضل من بناء القوالب من خلال تضمين عدد من المكونات المطلوبة أو بناء قالب من نقطة الصفر في كل مرة.
    • دعم التضمين: يسمح ببناء قوالب من خلال تضمين قوالب أخرى.
    • صيغة مُختصَرة للتحكم في المتغيرات والحلقات.
    • القدرة على ترشيح قيم المتغيرات على مستوى القالب مثل جعل المتغيرات بأحرف كبيرة أو تنسيق قيمة التاريخ.
    • القدرة على توليد تنسيقات الخرج بتنسيقات مختلفة عن تنسيق HTML مثل تنسيق JSON أو XML.
    • دعم العمليات والتدفق غير المتزامن.
    • ميزات من طرف العميل: إذا أمكن استخدام محرّك قوالب من طرف العميل، فسيسمح ذلك بإمكانية إجراء جميع أو معظم التقديم من طرف العميل.

سنستخدم في مشروعنا محرك القوالب Pug (وهو محرك Jade الذي أُعيدت تسميته مؤخرًا) الذي يُعَد من أشهر لغات قوالب Express/جافا سكريبت ويدعمه المولّد.

محرك تنسيق أو شيفرة CSS الذي يجب استخدامه

يتيح مولّد تطبيقات Express إنشاء مشروع مضبوط لاستخدام أكثر محركات تنسيق أو شيفرة CSS شيوعًا مثل LESS و SASS و Compass و Stylus.

ملاحظة: تحتوي لغة CSS على بعض القيود التي تصعّب إنجاز بعض المهام، ولكن تتيح محركات تنسيق أو شيفرة CSS استخدام صيغة أقوى لتعريف شيفرة CSS ثم تصريف التعريف في شيفرة CSS قديمة وبسيطة لتستخدمها المتصفحات.

يجب أن تستخدم محرك تنسيقات يسمح لفريقك أن يكون أكثر إنتاجية، إذ سنستخدم في مشروعنا شيفرة CSS الصرفة (الافتراضية) لأن متطلبات شيفرة CSS ليست معقدة بما يكفي لاستخدام شيء آخر.

قاعدة البيانات الواجب استخدامها

لا تستخدم أو تضمّن الشيفرة البرمجية المُولَّدة أيّ قاعدة بيانات، ويمكن لتطبيقات Express استخدام أيّ آلية قاعدة بيانات تدعمها بيئة Node، إذ لا يحدد Express أي سلوك أو متطلبات إضافية محددة لإدارة قاعدة البيانات (سنناقش كيفية التكامل مع قاعدة بيانات في مقال لاحق).

إنشاء المشروع

سننشئ مشروعًا بالاسم "express-locallibrary-tutorial" باستخدام مكتبة قوالب Pug بدون محرّك شيفرة CSS.

أولًا، انتقل إلى المكان الذي تريد إنشاء المشروع فيه ثم شغّل مولّد تطبيقات Express في موجّه الأوامر كما يلي:

express express-locallibrary-tutorial --view=pug

سينشئ المولّد ملفات المشروع ويسردها كما يلي:

  create : express-locallibrary-tutorial\
   create : express-locallibrary-tutorial\public\
   create : express-locallibrary-tutorial\public\javascripts\
   create : express-locallibrary-tutorial\public\images\
   create : express-locallibrary-tutorial\public\stylesheets\
   create : express-locallibrary-tutorial\public\stylesheets\style.css
   create : express-locallibrary-tutorial\routes\
   create : express-locallibrary-tutorial\routes\index.js
   create : express-locallibrary-tutorial\routes\users.js
   create : express-locallibrary-tutorial\views\
   create : express-locallibrary-tutorial\views\error.pug
   create : express-locallibrary-tutorial\views\index.pug
   create : express-locallibrary-tutorial\views\layout.pug
   create : express-locallibrary-tutorial\app.js
   create : express-locallibrary-tutorial\package.json
   create : express-locallibrary-tutorial\bin\
   create : express-locallibrary-tutorial\bin\www

   تغيير المجلد‫:
     > cd express-locallibrary-tutorial

   تثبيت الاعتماديات‫:
     > npm install

   ‫تشغيل التطبيق (باستخدام Bash على نظام لينكس أو ماك)
     > DEBUG=express-locallibrary-tutorial:* npm start

   ‫تشغيل التطبيق (باستخدام PowerShell على نظام ويندوز)
     > $ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start

   تشغيل التطبيق (باستخدام موجّه الأوامر على نظام ويندوز‫)
     > SET DEBUG=express-locallibrary-tutorial:* & npm start

يوفر المولّد في نهاية الخرج إرشادات حول كيفية تثبيت الاعتماديات (كما هو مذكور في الملف package.json) وكيفية تشغيل التطبيق على أنظمة تشغيل مختلفة.

ملاحظة: تعرّف الملفات التي أنشأها المولّد جميع المتغيرات بوصفها var، لذا افتح جميع الملفات المُولَّدة وغيّر تصريحات var إلى const قبل المتابعة، إذ سنفترض لاحقًا أنك أجريت هذا التعديل.

تشغيل الموقع الهيكلي

لدينا حاليًا مشروع هيكلي كامل، ولا يجري موقع الويب الكثير من الأمور حتى الآن، لكن الأمر يستحق تشغيله لإثبات أنه يعمل بنجاح.

أولًا، ثبّت الاعتماديات باستخدام الأمر install الذي يجلب جميع حزم الاعتماديات المُدرَجة في الملف package.json الخاص بالمشروع:

cd express-locallibrary-tutorial
npm install

ثانيًا، شغّل التطبيق من خلال استخدام الأمر التالي في موجّه أوامر ويندوز CMD:

SET DEBUG=express-locallibrary-tutorial:* & npm start

واستخدم الأمر التالي في Powershell ضمن نظام ويندوز:

ENV:DEBUG = "express-locallibrary-tutorial:*"; npm start

ملاحظة: لم نشرح أوامر Powershell بصورة أكبر في هذا المقال، إذ تفترض أوامر ويندوز التي سنستخدمها أنك تستخدم موجّه أوامر ويندوز CMD.

استخدم الأمر التالي في نظامي لينكس أو ماك أو إس:

DEBUG=express-locallibrary-tutorial:* npm start

ثالثًا، حمّل بعد ذلك العنوان http://localhost:3000/‎ في متصفحك للوصول إلى التطبيق.

يجب أن تشاهد صفحة متصفح تشبه ما يلي:

01 expressgeneratorskeletonwebsite

أصبح لديك الآن تطبيق Express يعمل بنجاح ويمكن الوصول إليه عبر المنفذ 3000.

ملاحظة: يمكنك بدء تشغيل التطبيق فقط باستخدام الأمر npm start. يفعّل تحديد المتغير DEBUG كما هو موضح فيما يلي تسجيل الطرفية أو تنقيح الأخطاء، فمثلًا سترى خرج تنقيح الأخطاء التالي عندما تزور الصفحة السابقة:

SET DEBUG=express-locallibrary-tutorial:* & npm start

> express-locallibrary-tutorial@0.0.0 start D:\github\mdn\test\exprgen\express-locallibrary-tutorial
> node ./bin/www

  express-locallibrary-tutorial:server Listening on port 3000 +0ms
GET / 304 490.296 ms - -
GET /stylesheets/style.css 200 4.886 ms - 111

تفعيل إعادة بدء الخادم عند إجراء تغييرات على الملف

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

يمكنك استخدام أداة مناسبة لهذا الغرض وهي nodemon، وتُثبَّت عادةً على المستوى العام بوصفها أداةً، ولكننا سنثبّتها ونستخدمها في مثالنا محليًا بوصفها اعتماديةً للمطور، بحيث يحصل عليها أيّ مطور يعمل على المشروع تلقائيًا عند تثبيت التطبيق. استخدم الأمر التالي في المجلد الجذر للمشروع للهيكلي:

npm install --save-dev nodemon

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

npm install -g nodemon

إذا فتحتَ الملف package.json الخاص بمشروعك، فسترى الآن قسمًا جديدًا مع الاعتمادية التالية:

"devDependencies": {
    "nodemon": "^2.0.4"
}

بما أننا لم نثبّت الأداة على المستوى العام، فلا يمكننا تشغيلها من سطر الأوامر (إلا في حالة إضافتها إلى المسار)، ولكن يمكننا استدعاؤها من سكريبت npm، لأن مدير الحزم npm على علم بكل شيء عن الحزم المُثبَّتة. ابحث عن القسم scripts في الملف package.json الذي سيحتوي في البداية على سطر واحد يبدأ بكلمة "start"، لذا حدّثه بوضع فاصلة في نهاية هذا السطر، وضِف سطري "devstart" و "serverstart".

سيبدو قسم السكربتات scripts كما يلي في نظامي لينكس وماك أو إس:

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "nodemon ./bin/www",
    "serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart"
  },

واستخدم الأمر التالي في نظام ويندوز:

"serverstart": "SET DEBUG=express-locallibrary-tutorial:* & npm run devstart"

يمكننا الآن بدء الخادم بالطريقة السابقة نفسها تمامًا ولكن باستخدام الأمر devstart.

ملاحظة: إذا عدّلتَ الآن أيّ ملف في المشروع، فسيُعاد بدء الخادم، أو يمكنك إعادة بدء الخادم بكتابة rs في موجّه الأوامر في أيّ وقت، وستظل بحاجة إلى إعادة تحميل المتصفح لتحديث الصفحة.

يجب الآن استدعاء الأمر "npm run <scriptname>‎" بدلًا من مجرد استخدام npm start، لأن "start" هو أمر npm يُربَط بالسكريبت. كان بإمكاننا استبدال الأمر في السكربت start ولكننا نريد فقط استخدام الأداة nodemon أثناء عملية التطوير، لذلك من المنطقي إنشاء أمر سكربت جديد.

يُعَد الأمر serverstart المُضاف إلى قسم السكريبتات scripts في الملف package.json مثالًا جيدًا، إذ يعني استخدام هذا الأسلوب أنك لم تعد مضطرًا إلى كتابة أمر طويل لبدء الخادم. لاحظ أن الأمر المحدد المضاف إلى السكريبت يعمل على نظام ماك أو لينكس فقط.

المشروع الناتج

لنطّلع الآن على المشروع الذي أنشأناه.

بنية المجلد

يمتلك المشروع المُولَّد الآن بنية الملفات التالية (الملفات هي العناصر التي ليس أولها "/") بعد تثبيت الاعتماديات. يعرّف الملف package.json اعتماديات التطبيق ومعلومات أخرى، ويعرّف سكريبتًا لبدء التشغيل يستدعي نقطة الدخول إلى التطبيق التي هي ملف جافا سكربت "‎/bin/www"، ممّا يؤدي إلى إعداد معالجة أخطاء التطبيق ثم تحميل الملف app.js لينفّذ بقية العمل. تُخزَّن وجهات Routes التطبيق في وحدات منفصلة ضمن المجلد "‎/routes‎"، وتُخزَّن القوالب في المجلد "‎/views".

express-locallibrary-tutorial
    app.js
    /bin
        www
    package.json
    package-lock.json
    /node_modules
        [about 6700 subdirectories and files]
    /public
        /images
        /javascripts
        /stylesheets
            style.css
    /routes
        index.js
        users.js
    /views
        error.pug
        index.pug
        layout.pug

سنشرح في الأقسام التالية هذه الملفات بمزيد من التفصيل.

الملف package.json

يعرّف الملف package.json اعتماديات التطبيق ومعلومات أخرى كما يلي:

{
  "name": "express-locallibrary-tutorial",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "morgan": "~1.9.1",
    "pug": "2.0.0-beta11"
  },
  "devDependencies": {
    "nodemon": "^2.0.4"
  }
}

تتضمن الاعتماديات الحزمة express وحزمة محرّك العروض المختار pug، وتوجد الحزم التالية المفيدة في العديد من تطبيقات الويب:

  • cookie-parser: تُستخدَم لتحليل ترويسة ملف تعريف الارتباط Cookie وملء req.cookies الذي يوفّر تابعًا ملائمًا للوصول إلى معلومات ملفات تعريف الارتباط.
  • debug: أداة مساعدة صغيرة لتنقيح أخطاء Node المُصمَّمة على غرار تقنية تنقيح أخطاء Node الأساسية.
  • morgan: برمجية وسيطة لتسجيل طلبات HTTP خاصة ببيئة Node.
  • http-errors: تنشئ أخطاء HTTP عند الحاجة (لمعالجة أخطاء Express).

يعرّف قسم السكريبتات scripts أولًا السكريبت "start"، وهو السكريبت الذي نستدعيه عند استدعاء الأمر npm start لبدء الخادم، إذ أضاف مولّد تطبيقات Express هذا السكربت. يمكنك أن ترى من تعريف السكريبت أنه يمثّل بداية ملف جافا سكريبت "‎./bin/www" باستخدام node.

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "nodemon ./bin/www",
    "serverstart": "DEBUG=express-locallibrary-tutorial:* npm run devstart"
  },

يمكن استخدام السكريبتات devstart و serverstart لبدء الملف "‎./bin/www" نفسه باستخدام nodemon بدلًا من node.

الملف www

يُعَد الملف "‎/bin/www" نقطة الدخول إلى التطبيق، وأول شيء يفعله هو استدعاء الدالة require()‎ لطلب نقطة الدخول الحقيقية إلى التطبيق (أي الملف app.js في جذر المشروع)، والذي يضبط ويعيد كائن تطبيق express()‎.

#!/usr/bin/env node

/**
 * اعتماديات الوحدة
 */

const app = require("../app");

ملاحظة: تُعَد الدالة require()‎ دالة Node عامة تُستخدَم لاستيراد الوحدات إلى الملف الحالي. نحدد في مثالنا وحدة app.js باستخدام مسار نسبي ونحذف امتداد الملف الاختياري (‎.js).

تُعِد بقية الشيفرة البرمجية في هذا الملف خادم HTTP الخاص ببيئة Node مع إعداد app على منفذ معين (مُحدَّد في متغير بيئة أو بالقيمة 3000 عند عدم تحديد هذا المتغير)، وتبدأ بالاستماع والإبلاغ عن أخطاء واتصالات الخادم. لا تحتاج حاليًا إلى معرفة أي شيء آخر عن الشيفرة البرمجية، فكل شيء في هذا الملف هو شيفرة متداولة، ولكن لا تتردد في الاطلاع عليها إن أردتَ ذلك.

الملف app.js

ينشئ هذا الملف كائن تطبيق express (يسمى app اصطلاحيًا)، ويُعِد التطبيق باستخدام إعدادات وبرمجيات وسيطة متنوعة مختلفة، ثم يصدّر التطبيق من الوحدة. توضّح الشيفرة البرمجية التالية أجزاء الملف التي تنشئ وتصدر كائن التطبيق:

const express = require("express");
const app = express();
// …
module.exports = app;

وهو الكائن module.exports في ملف نقطة الدخول www كما ذكرنا سابقًا، حيث يُزوَّد المستدعِي بهذا الكائن عند استيراد هذا الملف.

لنتعرّف على الملف app.js بالتفصيل. أولًا، نستورد بعض مكتبات Node المفيدة إلى الملف باستخدام الدالة require()‎ بما في ذلك http-errors و express و morgan و cookie-parser التي نزّلناها مسبقًا لتطبيقنا باستخدام مدير حزم npm، ومكتبة path وهي مكتبة Node أساسية لتحليل مسارات الملفات والمجلدات.

const createError = require("http-errors");
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");

نطلب بعد ذلك باستخدام الدالة require()‎ وحدات من مجلد الوجهات "routes"، إذ تحتوي هذه الوحدات أو الملفات على شيفرة برمجية للتعامل مع مجموعات معينة من "الوجهات" (مسارات URL). إذا أردنا توسيع التطبيق الهيكلي لسرد جميع الكتب في المكتبة مثلًا، فسنضيف ملفًا جديدًا للتعامل مع الوجهات المتعلقة بالكتب.

const indexRouter = require("./routes/index");
const usersRouter = require("./routes/users");

ملاحظة: استوردنا الوحدة، ولم نستخدم وجهاتها حتى الآن، ولكن سيحدث ذلك لاحقًا.

ننشئ بعد ذلك الكائن app باستخدام وحدة express المستوردة، ثم نستخدمها لإعداد محرك العروض (أو القوالب)، إذ أن هناك قسمان لإعداد المحرك هما: ضبط قيمة "views" لتحديد المجلد الذي ستُخزَّن القوالب فيه، وهو في حالتنا المجلد الفرعي "‎/views"، ثم ضبط قيمة "view engine" لتحديد مكتبة القوالب، وهي في حالتنا "pug".

const app = express();

// إعداد محرّك العروض
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");

تستدعي المجموعة التالية من الدوال app.use()‎ لإضافة مكتبات البرمجيات الوسيطة التي استوردناها سابقًا إلى سلسلة معالجة الطلبات، فمثلًا هناك حاجة إلى استخدام express.json()‎ و express.urlencoded()‎ لملء متن الطلب req.body بحقول الاستمارة. نستخدم أيضًا بعد هذه المكتبات البرمجيةَ الوسيطة express.static التي تجعل إطار عمل Express يخدّم جميع الملفات الثابتة في المجلد "‎/public" ضمن جذر المشروع.

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.use(express.static(path.join(__dirname, "public")));

ضبطنا جميع البرمجيات الوسيطة الأخرى، وسنضيف الآن شيفرة معالجة الوجهات (التي استوردناها سابقًا) إلى سلسلة معالجة الطلبات، إذ ستعرّف الشيفرة المستوردة وجهات معينة لأجزاء مختلفة من الموقع:

app.use("/", indexRouter);
app.use("/users", usersRouter);

ملاحظة: تُعامَل المسارات المحددة السابقة ('/' و '‎/users') بوصفها بادئةً للوِجهات المُعرَّفة في الملفات المستوردة، فمثلًا إذا عرّفت وحدةُ المستخدمين users المُستورَدة وجهة المسار ‎/profile، فيمكنك الوصول إلى هذا الوجهة من خلال ‎/users/profile (سنتحدث أكثر عن الوِجهات في مقال لاحق).

تضيف البرمجيات الوسيطة الأخيرة في الملف توابع معالجة للأخطاء واستجابات HTTP 404:

// التقاط 404 وتوجيه معالج الخطأ
app.use((req, res, next) => {
  next(createError(404));
});

// معالج الخطأ
app.use((err, req, res, next) => {
  // ‫ضبط locals، وتوفير خطأ في عملية التطوير فقط
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // تقديم صفحة الخطأ
  res.status(err.status || 500);
  res.render("error");
});

ضُبِط كائن تطبيق Express (أو app) كاملًا الآن، والخطوة الأخيرة هي إضافته إلى module.exports، مما يسمح بأن يستورده الملف ‎/bin/www.

module.exports = app;

الوجهات

اطّلع على ملف الوجهات "‎/routes/users.js" التالي، حيث تشترك ملفات الوجهات ببنية مماثلة، لذلك لا حاجة لعرض الملف index.js أيضًا. يحمّل هذا الملف أولًا الوحدة express ويستخدمها للحصول على الكائن express.Router، ثم يحدد وجهةً لهذا الكائن ويصدِّر الموجّه من الوحدة، مما يسمح باستيراد الملف في app.js.

const express = require("express");
const router = express.Router();

/* الحصول على قائمة المستخدمين */
router.get("/", (req, res, next) => {
  res.send("respond with a resource");
});

module.exports = router;

تعرّف الوجهة دالة رد نداء callback ستُستدعَى عند اكتشاف طلب HTTP من النوع GET بالنمط الصحيح، إذ يُعَد نمط المطابقة هو الوجهة المُحدَّدة عند استيراد الوحدة ('‎/users')، إضافةً إلى كل ما جرى تعريفه في هذا الملف ('/')، وبالتالي ستُستخدَم هذه الوجهة عند تلقي عنوان URL للمستخدمين /users/.

ملاحظة: جرب ذلك من خلال تشغيل الخادم باستخدام node وزيارة عنوان URL في متصفحك http://localhost:3000/users/‎، ويجب أن ترى الرسالة "respond with a resource".

تمتلك دالة رد النداء الوسيط الثالث next، وبالتالي هي دالة وسيطة بدلًا من كونها دالة رد نداء بسيطة للوجهة. لا تستخدم الشيفرة البرمجية الوسيط next حاليًا، ولكنه مفيدٌ مستقبلًا إذا أردتَ إضافة معالجات وجهات متعددة إلى مسار الوجهة '/'.

العروض أو القوالب

تُخزَّن العروض (أو القوالب) في المجلد "‎/views" (كما هو مُحدَّد في الملف app.js) وتُمنَح امتداد الملف ‎.pug، ويُستخدَم التابع Response.render()‎ لتصيير قالب محدد مع قيم المتغيرات المُسمَّاة الممرَّرة في كائن، ثم إرسال النتيجة بوصفها استجابة. يمكنك أن ترى في الشيفرة التالية من الملف "‎/routes/index.js" كيف تصيّر هذه الوجهة استجابةً باستخدام القالب "index" الذي يمرّر متغير القالب "title".

/* الحصول على الصفحة الرئيسية */
router.get("/", (req, res, next) => {
  res.render("index", { title: "Express" });
});

القالب المقابل للوجهة السابقة مذكور فيما يلي (index.pug). سنتحدث أكثر عن الصيغة لاحقًا، ولكن كل ما تحتاج إلى معرفته الآن هو أن المتغير title (مع القيمة "Express") يُدرَج في المكان المُحدَّد في القالب.

extends layout

block content
  h1= title
  p Welcome to #{title}

تحدى نفسك

أنشئ وجهةً جديدة في الملف "‎/routes/users.js" تعرض النص "You're so cool" على العنوان /users/cool/، واختبرها من خلال تشغيل الخادم وزيارة العنوان http://localhost:3000/users/cool/‎ في متصفحك.

الخلاصة

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

ترجمة -وبتصرُّف- للمقالين Express Tutorial: The Local Library website و Express Tutorial Part 2: Creating a skeleton website.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...