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

تطبيق عملي لتعلم Express - الجزء الخامس: النشر في بيئة الإنتاج


Ola Abbas

أنشأتَ واختبرتَ موقع المكتبة المحلية LocalLibrary، ويجب الآن تثبيته على خادم ويب عام ليصل إليه موظفو المكتبة وأعضاؤها عبر الإنترنت. يقدّم هذا المقال نظرة عامة حول كيفية البحث عن مضيف لنشر موقعك، وما عليك فعله لتجهيز موقعك لمرحلة الإنتاج.

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

عملتَ حتى الآن في بيئة تطوير باستخدام خادم ويب تطوير Express/Node لمشاركة موقعك على المتصفح أو الشبكة المحلية، وشغّلتَ موقعك باستخدام إعدادات تطوير (غير آمنة) بحيث يمكن الوصول إلى معلومات تنقيح الأخطاء والمعلومات الخاصة الأخرى. يجب عليك أولًا تنفيذ الخطوات التالية قبل أن تتمكّن من استضافة موقع ويب خارجيًا:

  • اختيار بيئة لاستضافة تطبيق Express.
  • إجراء بعض التغييرات على إعدادات مشروعك.
  • إعداد بنية تحتية على مستوى الإنتاج لتخديم موقع الويب.

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

ما هي بيئة الإنتاج؟

بيئة الإنتاج هي البيئة التي يوفّرها حاسوب الخادم إذ ستشغِّل موقعك للاستخدام الخارجي، وتشمل هذه البيئة ما يلي:

  • عتاد الحاسوب الذي يعمل عليه الموقع.
  • نظام التشغيل، مثل لينكس أو ويندوز.
  • وقت التشغيل الخاص بلغة البرمجة ومكتبات أطر العمل التي كُتِب عليها موقعك.
  • خادم الويب المُستخدَم لتخديم الصفحات والمحتويات الأخرى، مثل خادم إنجن إكس Nginx وأباتشي Apache.
  • البنية التحتية لخادم الويب وتتضمن خادم الويب والوكيل العكسي Reverse Proxy وموازن الحِمل Load Balancer وغير ذلك.
  • قواعد البيانات التي يعتمد عليها موقعك.

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

يشار إلى هذا النوع من عتاد المعالجة والتشبيك الذي يمكن الوصول إليه عن بُعد باسم البنية التحتية كخدمة Infrastructure as a Service -أو IaaS اختصارًا. يوفّر العديد من بائعي خدمة IaaS خيارات التثبيت المُسبَق لنظام تشغيل معين، والذي يجب تثبيت مكونات بيئتك الإنتاجية الأخرى عليه، ويسمح لك البائعون الآخرون باختيار بيئات كاملة الميزات، ويمكن أن يتضمن ذلك إعداد بيئة Node الكاملة.

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

يدعم مزوّدو الاستضافة الآخرون إطار عمل Express بوصفه جزءًا من استضافة المنصة كخدمة Platform as a Service -أو PaaS اختصارًا، فلا داعي للقلق في هذا النوع من الاستضافة بشأن معظم أجزاء بيئتك الإنتاجية (الخوادم وموازنو الحِمل load balancers وغيرها) لأن المنصة المضيفة تهتم بهذه الأشياء نيابةً عنك، مما يجعل النشر سهلًا جدًا، لأنك تحتاج فقط إلى التركيز على تطبيق الويب وليس على بنية الخادم التحتية الأخرى.

سيختار بعض المطورين المرونة المتزايدة التي توفرها استضافة IaaS على حساب استضافة PaaS، بينما سيقدّر المطورون الآخرون تقليل تكاليف الصيانة وسهولة توسيع نطاق استضافة PaaS. يكون إعداد موقعك على نظام PaaS أسهل بكثير في البداية، وهذا ما سنفعله في هذا المقال.

ملاحظة: إذا اخترت مزوّد استضافة متوافق مع Node/Express، فيجب أن يقدّم إرشادات حول كيفية إعداد موقع Express باستخدام عمليات ضبط مختلفة لخادم الويب وخادم التطبيق والوكيل العكسي وغير ذلك.

اختيار مزود الاستضافة

يوجد العديد من مزوّدات الاستضافة المعروفة التي تدعم بنشاط أو تعمل بصورة جيدة مع بيئة Node و Express، ويوفّر هؤلاء البائعون أنواعًا مختلفة من البيئات (IaaS و PaaS) ومستويات مختلفة من موارد المعالجة والشبكات بأسعار مختلفة.

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

إليك بعض الأشياء التي يجب مراعاتها عند اختيار المضيف:

  • مدى انشغال موقعك المُحتمَل وتكلفة البيانات وموارد المعالجة المطلوبة لتلبية هذا المطلب.
  • مستوى الدعم للتوسّع أفقيًا (إضافة المزيد من الأجهزة) وعموديًا (الترقية إلى أجهزة أقوى) وتكاليف ذلك.
  • مكان مراكز بيانات المزوّد، أي المكان الذي يكون الوصول إليه أسرع.
  • أداء وقت التشغيل ووقت التعطل السابقَين للمضيف.
  • الأدوات المتوفرة لإدارة الموقع، لمعرفة إذا كانت سهلة الاستخدام وآمنة، مثل استخدام بروتوكول SFTP أو استخدام بروتوكول FTP.
  • أطر العمل المبنية مسبقًا لمراقبة خادمك.
  • القيود المعروفة، إذ سيوقِف بعض المضيفين عمدًا خدمات معينة مثل البريد الإلكتروني، ويقدّم البعض الآخر فقط عددًا معينًا من ساعات "النشاط" في بعض مستويات الأسعار، أو يقدّم فقط قدرًا صغيرًا من التخزين.
  • الفوائد الإضافية، إذ ستقدّم بعض المزوّدات أسماء نطاقات مجانية ودعمًا لشهادات SSL التي يمكن أن يتعيّن عليك دفع ثمنها.
  • معرفة ما إذا كان المستوى "المجاني" الذي تعتمد عليه تنتهي صلاحيته بمرور الوقت، وما إذا كانت تكلفة التهجير Migrating إلى مستوًى أغلى تعني أنه كان من الأفضل استخدام بعض الخدمات الأخرى من البداية.

هناك عددٌ قليل جدًا من المواقع التي توفر بيئات معالجة "مجانية" مخصصة للتقييم والاختبار في البداية، وتكون عادةً بيئات مُقيَّدة أو محدودة الموارد إلى حدٍ ما، ويجب أن تدرك أنه يمكن أن تنتهي صلاحيتها بعد فترة أولية أو يكون لديها قيود أخرى، ولكنها رائعة لاختبار المواقع ذات حركة المرور المنخفضة في بيئة مُستضافة، ويمكن أن توفر تهجيرًا سهلًا للدفع مقابل المزيد من الموارد عندما يصبح موقعك أكثر انشغالًا. تشمل الخيارات الشائعة في هذه الفئة Railway و Python Anywhere و Amazon Web Services و Microsoft Azure وغير ذلك.

يقدّم معظم المزوّدين مستوًى أساسيًا مخصصًا لمواقع الإنتاج الصغيرة، والذي يوفّر مستويات أكثر فائدة من قدرة المعالجة وقيودًا أقل. يُعَد Heroku و Digital Ocean و Python Anywhere أمثلة على مزودي الاستضافة المشهورة التي لديها مستوى معالجة أساسي غير مكلف نسبيًا (في نطاق يتراوح بين 5 و 10 دولارات أمريكية شهريًا).

ملاحظة: تذكّر أن السعر ليس معيار الاختيار الوحيد، فإذا كان موقعك ناجحًا، فيمكن أن تكون قابلية التوسع هي الأهم.

تجهيز موقعك للنشر

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

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

ضبط قاعدة البيانات

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

إذا كان مزود الاستضافة الخاص بك داعمًا لمتغيرات البيئة من خلال واجهة الويب، ستكون إحدى الطرق لتحقيق ما سبق هي جعل الخادم يحصل على عنوان URL لقاعدة البيانات من متغير البيئة، لذلك سنعدّل موقع المكتبة المحلية LocalLibrary للحصول على معرّف URI لقاعدة البيانات من بيئة نظام التشغيل (إذا كان معرّفًا)، وإلّا فسنستخدم قاعدة بيانات التطوير الخاصة بنا.

افتح الملف app.js وابحث عن السطر الذي يضبط متغير اتصال قاعدة بيانات MongoDB، والذي سيبدو كما يلي:

const mongoDB =
  "mongodb+srv://your_user_name:your_password@cluster0.lz91hw2.mongodb.net/local_library?retryWrites=true&w=majority";

ضع الشيفرة التالية مكان السطر السابق، إذ تستخدم هذه الشيفرة process.env.MONGODB_URI للحصول على سلسلة الاتصال النصية من متغير البيئة MONGODB_URI إذا جرى ضبطه، واستخدم عنوان URL لقاعدة بياناتك بدلًا من العنصر البديل فيما يلي:

// إعداد‫ اتصال mongoose
const dev_db_url =
  const mongoose = require("mongoose");
mongoose.set("strictQuery", false);

const dev_db_url =
  "mongodb+srv://your_user_name:your_password@cluster0.lz91hw2.mongodb.net/local_library?retryWrites=true&w=majority";
const mongoDB = process.env.MONGODB_URI || dev_db_url;

main().catch((err) => console.log(err));
async function main() {
  await mongoose.connect(mongoDB);
}

ضبط متغير البيئة NODE_ENV على القيمة production

يمكننا إزالة تعقّب المكدس في صفحات الخطأ من خلال ضبط متغير البيئة NODE_ENV على قيمة الإنتاج 'production'، إذ يُضبَط على قيمة التطوير 'development' افتراضيًا. يؤدي ضبط المتغير على قيمة الإنتاج إلى إنشاء رسائل خطأ أقل تفصيلًا، بالإضافة إلى التخزين المؤقت لقوالب العرض وملفات CSS المُولَّدة من توسّعات شيفرة CSS، وتشير الاختبارات إلى أن ضبط متغير البيئة NODE_ENV على الإنتاج يمكن أن يحسن أداء التطبيق بمقدار ثلاثة أضعاف. يمكن إجراء هذا التغيير إما باستخدام export، أو ملف بيئة، أو نظام تهيئة لنظام التشغيل.

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

التسجيل المناسب

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

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

const debug = require("debug")("author");

// عرض استمارة‫ تحديث المؤلف باستخدام GET
exports.author_update_get = asyncHandler(async (req, res, next) => {
  const author = await Author.findById(req.params.id).exec();
  if (author === null) {
    // لا توجد نتائج
    debug(`id not found on update: ${req.params.id}`);
    const err = new Error("Author not found");
    err.status = 404;
    return next(err);
  }

  res.render("author_form", { title: "Update Author", author: author });
});

يمكنك بعد ذلك تفعيل مجموعة معينة من السجلات من خلال تحديدها بوصفها قائمة مفصول بين عناصرها بفواصل في متغير بيئة DEBUG، ويمكنك ضبط المتغيرات لعرض سجلات المؤلف والكتاب كما هو موضح فيما يلي (المحارف البديلة Wildcards مدعومة أيضًا):

# في نظام ويندوز
set DEBUG=author,book

# في نظام لينكس
export DEBUG="author,book"

ملاحظة: يمكن أن تحل استدعاءات debug محل التسجيل الذي ربما طبّقته مسبقًا باستخدام console.log()‎ أو console.error()‎، لذا ضع التسجيل باستخدام وحدة debug مكان استدعاءات console.log()‎ في شيفرتك البرمجية، وشغّل التسجيل وأوقفه في بيئة التطوير من خلال ضبط المتغير DEBUG ولاحظ تأثير ذلك على التسجيل.

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

استخدم ضغط gzip أو deflate للاستجابة

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

يمكنك إضافة ذلك إلى موقعك باستخدام برمجية الضغط الوسيطة compression، لذا ثبّتها في جذر مشروعك من خلال تشغيل الأمر التالي:

npm install compression

افتح الملف "‎./app.js" واطلب مكتبة الضغط. ضِف مكتبة الضغط إلى سلسلة البرمجيات الوسيطة باستخدام التابع use()‎ الذي يجب أن يظهر قبل أي وجهات Routes تريد ضغطها (جميع الوجهات في حالتنا):

const catalogRouter = require("./routes/catalog"); // استيراد الوجهات ‫لمنطقة الدليل "catalog" من موقعك
const compression = require("compression");

// إنشاء ‫كائن تطبيق Express
const app = express();

// …

app.use(compression()); // ضغط جميع الوجهات

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

app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/catalog", catalogRouter); // إضافة وجهات‫ الدليل catalog إلى سلسلة البرمجيات الوسيطة

// …

ملاحظة: لن تَستخدمَ هذه البرمجيات الوسيطة لموقع الويب الذي يمتلك حركة مرور عالية في بيئة الإنتاج، لذا يمكنك استخدام وكيل عكسي مثل Nginx بدلًا من ذلك.

استخدام حزمة Helmet للحماية من الثغرات المعروفة

تُعَد Helmet حزمة برمجيات وسيطة يمكنها ضبط ترويسات HTTP المناسبة التي تساعد في حماية تطبيقك من ثغرات الويب المعروفة. اطّلع على توثيقها للحصول على مزيد من المعلومات حول الترويسات التي تضبطها والثغرات الأمنية التي تحميك منها.

ثبّتها في جذر مشروعك من خلال تشغيل الأمر التالي:

npm install helmet

افتح الملف "‎./app.js" واطلب مكتبة helmet، ثم ضِف الوحدة إلى سلسلة البرمجيات الوسيطة باستخدام التابع use()‎:

const compression = require("compression");
const helmet = require("helmet");

// إنشاء كائن ت‫طبيق Express
const app = express();

// إض‫افة حزمة helmet إلى سلسلة البرمجيات الوسيطة
// ضبط‫ ترويسات CSP للسماح بتخديم Bootstrap و Jquery
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      "script-src": ["'self'", "code.jquery.com", "cdn.jsdelivr.net"],
    },
  }),
);

// …

يمكن أن نضيف التابع app.use(helmet());‎ لإضافة مجموعة فرعية من الترويسات المتعلقة بالأمان والتي تكون منطقية لمعظم المواقع، ولكننا نضمّن بعض سكربتات بوتستراب bootstrap و jQuery في قالب موقع المكتبة المحلية LocalLibrary الأساسي، مما يؤدي إلى انتهاك سياسة أمان المحتوى Content Security Policy -أو CSP اختصارًا- الافتراضية الخاصة بحزمة helmet، والتي لا تسمح بتحميل السكربتات العابرة للمواقع. يمكن السماح بتحميل هذه السكربتات من خلال تعديل ضبط helmet بحيث تُضبَط موجّهات CSP للسماح بتحميل السكربت من النطاقات المُشار إليها، ويمكنك بالنسبة لخادمك إضافة أو تعطيل ترويسات محددة حسب الحاجة باتباع الإرشادات الخاصة باستخدام helmet.

إضافة معدل محدود إلى وجهات واجهة برمجة التطبيقات API

تُعَد Express-rate-limit حزمة برمجية وسيطة يمكن استخدامها للحد من الطلبات المتكررة لواجهات برمجة التطبيقات API والنقاط النهائية، فهناك العديد من الأسباب التي يمكن أن تؤدي إلى زيادة الطلبات على موقعك مثل هجمات حجب الخدمة أو هجمات القوة الغاشمة أو حتى مجرد عميل أو سكربت لا يتصرف كما هو متوقع، ويمكن أن تُحاسَب على حركة المرور الإضافية بغض النظر عن مشاكل الأداء التي يمكن أن تنشأ عن كثرة الطلبات التي تتسبب في إبطاء خادمك. يمكن استخدام حزمة Express-rate-limit للحد من عدد الطلبات التي يمكن إجراؤها على وجهة معينة أو مجموعة من الوِجهات.

يمكنك الاطلاع على مقال الهجمات الأمنية Security Attacks في الشبكات الحاسوبية على أكاديمية حسوب لمزيد من المعلومات حول أنواع الهجمات الأمنية.

ثبّت هذه الحزمة في جذر مشروعك من خلال تشغيل الأمر التالي:

npm install express-rate-limit

افتح الملف "‎./app.js" واطلب مكتبة express-rate-limit كما يلي، ثم ضِف الوحدة إلى سلسلة البرمجيات الوسيطة باستخدام التابع use()‎:

const compression = require("compression");
const helmet = require("helmet");

const app = express();

// إعداد محدِّد المعدل إلى عشرين طلبًا في الدقيقة كحد أعلى
const RateLimit = require("express-rate-limit");
const limiter = RateLimit({
  windowMs: 1 * 60 * 1000, // ‫1 دقيقة
  max: 20,
});
// طبّق محدّد المعدّل على جميع الطلبات
app.use(limiter);

// …

ملاحظة:

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

تطبيق عملي: تثبيت موقع المكتبة المحلية LocalLibrary على منصة Railway

يقدّم هذا القسم شرحًا عمليًا لكيفية تثبيت موقع المكتبة المحلية LocalLibrary على منصة Railway.

سبب استخدام Railway

اخترنا استخدام منصة Railway لعدة أسباب هي:

  • تمتلك Railway مستوًى مجانيًا لخطة بداية مع بعض القيود، إذ من المهم أن تكون بأسعار مقبولة لجميع المطورين.

  • تهتم Railway بمعظم البنية التحتية، فلا حاجة للقلق بشأن الخوادم وموازني الحِمل والوكلاء العكسيين وغير ذلك، مما يجعل البدء أسهل بكثير.

  • تركّز Railway على تجربة المطور للتطوير والنشر، مما يؤدي إلى وجود منحنى تعليمي أسرع وأسلس من العديد من البدائل الأخرى.

  • تُعَد المهارات والمفاهيم التي ستتعلمها عند استخدام Railway قابلة للتحويل، إذ تمتلك Railway بعض الميزات الجديدة الممتازة، ولكن تستخدم خدماتُ الاستضافة الشائعة الأخرى العديدَ من الأفكار والأساليب نفسها.

  • لا تؤثر قيود الخدمات والخطط على استخدامنا لمنصة Railway في مثالنا، فمثلًا:

    • تقدّم خطة البداية 500 ساعة فقط من وقت النشر المستمر كل شهر و5 دولارات من الرصيد الذي يُستهلَك بناءً على الاستخدام، ويُعاد ضبط الساعات والرصيد ويجب إعادة نشر المشاريع في نهاية كل شهر. تعني هذه القيود أنه يمكنك تشغيل هذا المثال بصورة مستمرة لمدة 21 يومًا تقريبًا، ويُعَد ذلك أكثر من كافٍ للتطوير والاختبار، ولكن لن تتمكّن من استخدام هذه الخطة لموقع حقيقي للإنتاج.
    • تحتوي بيئة خطة البداية على 512 ميجابايت فقط من الذاكرة RAM و1 جيجابايت من ذاكرة التخزين، وهذا أكثر من كافٍ لمثالنا.
    • لا توجد سوى منطقة واحدة مدعومة وهي الولايات المتحدة الأمريكية حاليًا، إذ يمكن أن تكون الخدمة خارج هذه المنطقة أبطأ أو تحظرها القوانين المحلية.
    • يمكن العثور على قيود أخرى في توثيق خطط Railway للدفع.
  • تبدو الخدمة موثوقة جدًا، وإذا كانت مناسبة لك، فإن الأسعار يمكن التنبؤ بها، ويكون توسيع تطبيقك سهلًا جدًا.

  • تعَد Railway مناسبة لاستضافة مثالنا، ولكن يجب أن تأخذ الوقت الكافي لتحديد ما إذا كانت مناسبة لموقعك.

كيفية عمل Railway

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

تجعل Railway هذا الأمر سهلًا، إذ يمكنها التعرف تلقائيًا على العديد من أطر عمل وبيئات تطبيقات الويب المختلفة وتثبيتها بناءً على استخدامها "للمصطلحات الشائعة"، فمثلًا تتعرّف Railway على تطبيقات Node لأن لديها ملف package.json، ويمكنها تحديد مدير الحزم المُستخدَم للبناء من ملف "القفل Lock". إذا احتوى التطبيق على ملف package-lock.json مثلًا، فستعرف Railway أنها ستستخدم مدير حزم npm لتثبيت الحزم، وإذا وجدت yarn.lock فستعرف أنها ستستخدم yarn. ستبحث Railway -بعد تثبيت جميع الاعتماديات- عن سكربتات بالاسم "build" و "start" في ملف الحزمة، وستستخدمها لبناء وتشغيل الشيفرة البرمجية.

ملاحظة: تستخدم Railway حزمة Nixpacks للتعرف على العديد من أطر عمل تطبيقات الويب المكتوبة بلغات برمجة مختلفة. لا حاجة إلى معرفة أيّ شيء آخر لهذا المقال، ولكن يمكنك معرفة المزيد حول خيارات نشر تطبيقات Node في توثيق Nixpacks.

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

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

يجب وضع تطبيق Express الخاص بنا في مستودع غيت git وإجراء بعض التغييرات الطفيفة ليعمل تطبيقنا على Railway، ثم يمكننا إعداد حساب على Railway وتثبيت موقعنا وقاعدة البيانات وتجربة عميل Railway.

وهذا هو كل ما تحتاجه من معلومات في البداية.

إنشاء مستودع للتطبيق على غيت هب GitHub

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

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

هناك العديد من الطرق للعمل مع git، ومن أسهلها إعداد حساب على غيت هب أولًا وإنشاء المستودع عليه، ثم المزامنة معه محليًا كما يلي:

  1. انتقل إلى موقع GitHub الرسمي وأنشئ حسابًا عليه.
  2. انقر على ارتباط + في شريط الأدوات العلوي وحدّد خيار "مستودع جديد New repository" بعد تسجيل الدخول.
  3. املأ جميع الحقول في هذه الاستمارة، إذ يمكن أن تكون هذه الحقول غير إلزامية، ولكن يُوصَى بها بشدة.
    • أدخل اسم المستودع الجديد والوصف، فمثلًا يمكنك استخدام الاسم "express-locallibrary-tutorial" والوصف
      "Local Library website written in Express (Node)‎" (موقع المكتبة المحلية المكتوب باستخدام Express).
    • اختر الخيار Node في قائمة الاختيار Add .gitignore.
    • اختر الترخيص المفضل لديك في قائمة الاختيار Add license.
    • تحقق من تهيئة المستودع باستخدام README.

تحذير: سيجعل الوصول الافتراضي العام "Public" جميع الشيفرة البرمجية المصدرية -بما في ذلك اسم المستخدم وكلمة المرور لقاعدة البيانات- مرئيةً لأي شخص على الإنترنت، لذا تأكد من أن الشيفرة البرمجية المصدرية لا تقرأ اعتماديات إلّا من متغيرات البيئة ولا تحتوي على أيّ اعتماديات ثابتة، وإلّا حدد الخيار خاص "Private" للسماح فقط لأشخاص محدَّدين برؤية الشيفرة المصدرية.

  1. اضغط على إنشاء مستودع Create repository.
  2. انقر فوق الزر الأخضر نسخ Clone أو تنزيل Download في صفحة مستودعك الجديد.
  3. انسخ قيمة URL من حقل النص الموجود في مربع الحوار الذي يظهر، فإذا استخدمت اسم المستودع "express-locallibrary-tutorial"، فيجب أن يكون عنوان URL مثل العنوان: https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git.

انتهينا من إنشاء المستودع، ويجب الآن نسخه على حاسوبك المحلي باتباع الخطوات التالية:

أولًا، ثبّت git على حاسوبك المحلي، إذ يمكنك العثور على نسخ لأنظمة مختلفة.

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

git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git

سيؤدي هذا الأمر إلى إنشاء المستودع في المجلد الحالي.

ثالثًا، انتقل إلى مجلد المستودع باستخدام الأمر التالي:

cd express-locallibrary-tutorial

أخيرًا، انسخ ملفات تطبيقك المصدرية في مجلد المستودع، ثم اجعلها جزءًا من المستودع باستخدام git كما يلي:

أولًا، انسخ تطبيق Express إلى هذا المجلد باستثناء المجلد "‎/node_modules" الذي يحتوي على ملفات الاعتماديات التي يجب جلبها من مدير حزم npm حسب الحاجة.

ثانيًا، افتح موجه الأوامر أو الطرفية واستخدم الأمر add لإضافة جميع الملفات إلى git كما يلي:

git add -A

ثالثًا، استخدم الأمر status للتحقق من صحة جميع الملفات التي تريد تثبيتها commit، إذ نريد تضمين الملفات المصدرية، وليس الملفات الثنائية والمؤقتة وما إلى ذلك، إذ يجب أن تبدو كما يلي:

> git status

ويكون الخرج الناتج بعد تنفيذ هذا الأمر على النحو التالي:

On branch main
Your branch is up-to-date with 'origin/main'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   …

رابعًا، ثبّت باستخدام commit الملفات في مستودعك المحلي عندما تكون راضيًا عن النتيجة، إذ يكافئ ذلك الإقرار بالتغييرات وجعلها جزءًا رسميًا من المستودع المحلي.

git commit -m "First version of application moved into GitHub"

خامسًا، لم يتغيّر المستودع البعيد حتى الآن، لذا يجب مزامنة (باستخدام الأمر push) مستودعك المحلي مع مستودع GitHub البعيد باستخدام الأمر التالي:

git push origin main

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

ملاحظة: يمكنك الآن إنشاء نسخة احتياطية من شيفرة مشروعك البرمجية، إذ يمكن أن تكون بعض التغييرات التي سنجريها في الأقسام التالية مفيدة للنشر (أو للتطوير) على أي خدمة استضافة، ويمكن أن تكون بعض التغييرات الأخرى غير مفيدة. أفضل طريقة لذلك هي استخدام git لإدارة الإصدارات، إذ يمكنك باستخدامه الرجوع إلى إصدار سابق معين، ويمكنك الاحتفاظ به في فرع منفصل عن التغييرات الإنتاجية واختيار أيّ تغييرات للتنقل بين فروع الإنتاج والتطوير. يستحق تعلم غيت Git الجهد المبذول، لذا اطلع على مجموعة مقالات Git في أكاديمية حسوب. يُعَد نسخ ملفاتك في موقع آخر الطريقة الأسهل، ولكن يمكنك استخدام أيّ طريقة تتناسب مع معرفتك لنظام git.

تحديث التطبيق ليعمل على Railway

سنشرح في هذا القسم التغييرات التي يجب إجراؤها على تطبيق المكتبة المحلية LocalLibrary ليعمل على Railway، ولكن لن تمنعك هذه التغييرات من استخدام الاختبار وسير العمل المحلي الذي تعلمناه مسبقًا.

ضبط نسخة Node

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

>node --version
v16.17.1

افتح الملف package.json وأضِف المعلومات التالية في قسم engines > node (مع استخدام رقم النسخة في نظامك):

{
  "name": "express-locallibrary-tutorial",
  "version": "0.0.0",
  "engines": {
    "node": ">=16.17.1"
  },
  "private": true,
  // …

لاحظ أن هناك طرقًا أخرى لتوفير نسخة Node على Railway، ولكننا نستخدم الملف package.json لأنه الأسلوب الذي تدعمه العديد من الخدمات على نطاق واسع. لاحظ أيضًا أن Railway لن تستخدم بالضرورة نسخة Node الدقيقة التي تحددها، إذ ستستخدم نسخةً لها رقم النسخة الرئيسي نفسه.

الحصول على الاعتماديات وإعادة الاختبار

لنختبر الموقع مرةً أخرى ونتأكد من أنه لم يتأثر بأيٍّ من التغييرات التي أجريناها.

أولًا، يجب جلب الاعتماديات (تذكّر أننا لم ننسخ المجلد node_modules في شجرة git)، إذ يمكنك ذلك من خلال تشغيل الأمر التالي في طرفيتك ضمن جذر المشروع:

npm install

شغّل الموقع (اطّلع على فقرة اختبار الوجهات في مقال الوجهات والمتحكمات لمعرفة الأوامر ذات الصلة) وتحقق من أن الموقع لا يزال يتصرف كما هو متوقع.

حفظ التغييرات على غيت هب GitHub

احفظ الآن جميع التغييرات التي أجريتها على غيت هب، وأدخِل الأوامر التالية في الطرفية أثناء وجودك في مستودعك:

git add -A
git commit -m "Added files and changes required for deployment"
git push origin main

يجب أن نكون جاهزين الآن لبدء نشر موقع المكتبة المحلية LocalLibrary على Railway.

الحصول على حساب على Railway

يجب أولًا إنشاء حساب لبدء استخدام Railway باتباع الخطوات التالية:

  • اذهب إلى موقع Railway الرسمي وانقر على ارتباط تسجيل الدخول Login في شريط الأدوات العلوي.
  • اختر GitHub في النافذة المنبثقة لتسجيل الدخول باستخدام اعتماديات GitHub الخاصة بك.
  • يمكن أن تحتاج بعد ذلك إلى الانتقال إلى بريدك الإلكتروني والتحقق من حسابك.
  • ستسجل بعد ذلك الدخول إلى لوحة تحكم Railway.

النشر على Railway من GitHub

يجب الآن إعداد Railway لنشر موقع مكتبتنا من GitHub، لذا اختر أولًا خيار لوحة التحكم Dashboard من القائمة العلوية للموقع، ثم حدّد زر مشروع جديد New Project:

01 railway new project button

ستعرض Railway قائمةً بالخيارات الخاصة بالمشروع الجديد، بما في ذلك خيار نشر مشروع من قالب أنشأته لأول مرة في حسابك على GitHub، وعددًا من قواعد البيانات، لذا حدد خيار النشر Deploy from GitHub repo.

02 railway new project button deploy github repo

ستُعرَض جميع المشاريع في مستودعات GitHub التي شاركتها مع Railway أثناء عملية الإعداد، ولكنك ستختار مستودع GitHub الخاص بموقع المكتبة المحلية: ‎<user-name>/express-locallibrary-tutorial.

03 railway new project button deploy github selectrepo

أكّد النشر من خلال تحديد خيار النشر حالًا Deploy Now.

04 railway new project deploy confirm

ستحمّل Railway بعد ذلك مشروعك وتنشره، مع عرض التقدم في نافذة عمليات النشر Deployments، ثم سترى شيئًا يشبه ما يلي عند اكتمال النشر بنجاح:

05 railway project deploy

اختر الآن نافذة الإعدادات Settings، ثم انتقل إلى الأسفل إلى قسم النطاقات Domains، واضغط على زر توليد نطاق Generate Domain.

06 railway project generate domain

سيؤدي ذلك إلى نشر الموقع ووضع النطاق في مكان الزر كما هو موضح فيما يلي:

07 railway project domain

حدّد عنوان URL للنطاق لفتح تطبيق المكتبة. لاحظ فتح موقع المكتبة المحلية باستخدام بيانات التطوير الخاصة بك لأننا لم نحدّد قاعدة بيانات الإنتاج.

تجهيز وتوصيل قاعدة بيانات MongoDb

لننشئ الآن قاعدة بيانات MongoDB الخاصة بالإنتاج لاستخدامها بدلًا من استخدام بيانات التطوير، إذ سننشئ قاعدة البيانات بوصفها جزءًا من مشروع تطبيق Railway، بالرغم من أنه لا يوجد ما يمنعك من إنشائها في مشروعها المنفصل أو استخدام قاعدة بيانات MongoDB Atlas لبيانات الإنتاج، كما فعلت مع قاعدة بيانات التطوير.

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

08 railway project open no database

حدد قاعدة البيانات Database عندما يُطلَب منك تحديد نوع الخدمة لإضافتها.

09 railway database add

حدّد بعد ذلك خيار الإضافة Add MongoDB لبدء إضافة قاعدة البيانات.

10 railway database select type

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

11 railway project two services

حدّد خدمة MongoDB لعرض معلومات حول قاعدة البيانات، ثم افتح نافذة "الاتصال Connect" وانسخ "عنوان URL لاتصال Mongo"، وهو عنوان قاعدة البيانات.

12 railway mongodb connect

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

أدخِل اسم المتغير MONGODB_URI وعنوان URL للاتصال الذي نسخته لقاعدة البيانات، فالمتغير MONGODB_URI هو اسم متغير البيئة الذي ضبطنا التطبيق منه لقراءة عنوان قاعدة البيانات، وسيظهر لديك ما يلي:

13 railway variables database url

حدّد بعد ذلك زر الإضافة Add لإضافة المتغير.

تعيد Railway تشغيل تطبيقك عندما تحدّث المتغيرات. إذا فحصتَ الصفحة الرئيسية الآن، فيجب أن تظهِر قيمًا صفرية لأعداد الكائنات، إذ تعني التغييرات السابقة أننا نستخدم الآن قاعدة بيانات جديدة (فارغة).

متغيرات الضبط الأخرى

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

افتح خدمة التطبيق، ثم حدد نافذة المتغيرات Variables، إذ سترى أن المتغير MONGODB_URI مُعرَّف مسبقًا، واضغط على زر متغير جديد New Variable.

14 railway variables new

أدخل NODE_ENV بوصفه اسم المتغير الجديد و production بوصفه اسم البيئة، ثم اضغط على زر الإضافة Add.

15 railway variables new node env

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

ملاحظة: إذا أدرتَ إضافة بعض البيانات للاختبار، فيمكنك استخدام السكربت populatedb مع عنوان URL لقاعدة بيانات MongoDB الخاصة بالإنتاج كما ناقشنا في مقال استخدام قاعدة البيانات باستخدام مكتبة Mongoose.

تثبيت العميل

نزّل وثبّت عميل Railway لنظام تشغيلك المحلي باتباع التعليمات الواردة في توثيق Railway.

ستتمكن من تشغيل الأوامر بعد تثبيت العميل. تتضمن بعض العمليات الأكثر أهمية نشر المجلد الحالي لحاسوبك إلى مشروع Railway المرتبط به دون الحاجة للرفع على GitHub، وتشغيل مشروعك محليًا باستخدام الإعدادات نفسها الموجودة على خادم الإنتاج.

يمكنك الحصول على قائمة بجميع الأوامر الممكنة من خلال إدخال الأمر التالي في الطرفية:

railway help

تنقيح الأخطاء Debugging

يوفّر عميل Railway الأمر logs لإظهار السجلات الأخيرة (يتوفر سجل كامل على الموقع لكل مشروع):

railway logs

الخلاصة

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

ترجمة -وبتصرُّف- للمقال Express Tutorial Part 7: Deploying to production.

اقرأ المزيد


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

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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...