عندما يحتاج الواجهة الأمامية إلى خادم: بناء خط أنابيب CI/CD لتطبيقات SSR
لقد انتهيت للتو من إضافة ميزة جديدة في تطبيق Next.js الخاص بك. عملية البناء تمر محليًا. تدفع إلى الإنتاج. ولكن بدلاً من صفحة تعمل، يرى المستخدمون شاشة فارغة مع مؤشر تحميل دوار. عملية الخادم بدأت، لكنها لم تكن جاهزة فعليًا لمعالجة الطلبات.
هذه هي اللحظة التي تدرك فيها أن نشر واجهة أمامية مُقدَّمة من الخادم يختلف جوهريًا عن نشر موقع ثابت. خط الأنابيب الذي كان يعمل مع تطبيق React أحادي الصفحة (SPA) أو موقع Gatsby الثابت لن يكون كافيًا بعد الآن.
الفرق الجوهري: أنت تنشر خادمًا، وليس ملفات
مع الواجهة الأمامية الثابتة، ينتج عن البناء ملفات HTML و CSS و JavaScript. تقوم برفعها إلى شبكة توصيل المحتوى (CDN) أو مخزن، وتنتهي المهمة. النشر هو في الأساس عملية نسخ ملفات.
مع التقديم من الخادم (SSR)، يتضمن مخرجات البناء كودًا يعمل على جانب الخادم يجب تشغيله كعملية. أطر العمل مثل Next.js أو Nuxt أو Remix تُنشئ مجلدًا يحتوي على:
- كود JavaScript يعمل على الخادم
- حزم JavaScript للعميل
- أصول ثابتة مثل الصور والخطوط
- ملف نقطة دخول (غالبًا
server.js) يبدأ تشغيل التطبيق
يحتاج خط الأنابيب الخاص بك الآن إلى معالجة هذا المخرجات كتطبيق يعمل بشكل مستمر، وليس كمجموعة من الملفات ليتم تقديمها. هذا يغير كل شيء في كيفية البناء والاختبار والنشر.
الخطوة 1: البناء بالهدف الصحيح
خطوة البناء تبدو مشابهة للواجهة الأمامية الثابتة للوهلة الأولى. تقوم بتشغيل npm run build أو الأمر المكافئ لإطار العمل. لكن المخرجات مختلفة، وكذلك ما تفعله بها.
بالنسبة لـ SSR، يجب تعبئة مخرجات البناء في شيء يمكن تشغيله على خادم. إذا كنت تستخدم الحاويات، فهذا يعني إنشاء صورة Docker تتضمن:
- كود الخادم المبني
- تبعيات وقت التشغيل (إصدار Node.js، مكتبات النظام)
- أي ملفات تكوين مطلوبة في وقت التشغيل
- سكريبت نقطة الدخول
قد يبدو ملف Dockerfile الخاص بك شيئًا كهذا:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY .next ./.next
COPY public ./public
EXPOSE 3000
CMD ["node", ".next/standalone/server.js"]
التفصيل الرئيسي: أنت لا تنسخ كود المصدر بالكامل. أنت تنسخ فقط ما هو مطلوب لتشغيل التطبيق. هذا يحافظ على صغر حجم الصورة ويقلل من سطح الهجوم.
الخطوة 2: فحوصات الصحة ليست اختيارية
هنا تفشل العديد من خطوط أنابيب SSR. تبدأ الحاوية، تعمل العملية، ويفترض الجميع أن التطبيق يعمل. لكن "العملية قيد التشغيل" ليس مثل "التطبيق يمكنه تقديم الطلبات".
قد يبدأ تطبيقك بنجاح لكنه يفشل في عرض الصفحات بسبب:
- انتهاء مهلة اتصال قاعدة البيانات
- عدم إمكانية الوصول إلى واجهة برمجة تطبيقات خارجية
- متغيرات بيئة مفقودة
- خدمة مطلوبة غير جاهزة بعد
أضف نقطة نهاية لفحص الصحة إلى تطبيقك. عادةً ما تكون موجودة في /health أو /api/health وتعيد حالة 200 عندما يمكن للتطبيق معالجة الطلبات فعليًا. يجب على خط الأنابيب الخاص بك استدعاء نقطة النهاية هذه بعد النشر، قبل توجيه حركة المرور إلى الإصدار الجديد.
إذا فشل فحص الصحة، أوقف خط الأنابيب. لا تدع المستخدمين يرون صفحات خطأ أو حالات تحميل لا نهائية. يقوم الفريق بالتحقيق، وإصلاح المشكلة، وتشغيل خط الأنابيب مرة أخرى.
الخطوة 3: اختر استراتيجية النشر الخاصة بك
لديك مساران شائعان لنشر تطبيقات SSR: مباشرة على خادم أو داخل حاويات. لكل منهما آثار مختلفة على خط الأنابيب الخاص بك.
يوضح المخطط الانسيابي التالي خط أنابيب SSR الكامل، من البناء إلى النشر، مع نقطة قرار فحص الصحة الحرجة.
النشر المباشر على الخادم
تقوم بنسخ مخرجات البناء إلى خادم، وإيقاف العملية القديمة، وبدء العملية الجديدة. الاهتمام الحاسم هنا هو كيفية التعامل مع الانتقال.
إذا قتلت العملية القديمة فورًا، فإن أي طلبات تتم معالجتها حاليًا ستفشل. يرى المستخدمون أخطاء أثناء العمل. الحل هو الإيقاف التدريجي (graceful shutdown): يتوقف الخادم القديم عن قبول الطلبات الجديدة لكنه ينهي معالجة الطلبات الموجودة بالفعل. بمجرد اكتمالها، تخرج العملية بشكل نظيف. ثم يبدأ الخادم الجديد ويبدأ في استقبال حركة المرور.
يحتاج سكريبت خط الأنابيب الخاص بك إلى تنسيق هذا التسليم. إنه قابل للتنفيذ لكنه يتطلب برمجة ومراقبة دقيقة.
نشر الحاويات
تمنحك الحاويات تحكمًا أكبر. يبني خط الأنابيب صورة Docker جديدة، ويدفعها إلى سجل، وينشرها على منصة تنسيق الحاويات الخاصة بك.
إليك ملف Dockerfile أدنى يقوم بتعبئة تطبيق SSR المبني لنشر الحاوية:
FROM node:20-alpine
WORKDIR /app
# نسخ تبعيات الإنتاج
COPY package.json package-lock.json ./
RUN npm ci --only=production
# نسخ أصول الخادم والعميل المبنية
COPY .next ./.next
COPY public ./public
# كشف المنفذ الذي يستمع عليه التطبيق
EXPOSE 3000
# بدء الخادم
CMD ["node", ".next/standalone/server.js"]
مع Kubernetes، يصبح هذا تحديثًا دوريًا (rolling update):
- تبدأ حاوية جديدة بالصورة الجديدة
- تقوم الحاوية بتشغيل فحص الصحة الخاص بها
- بمجرد أن تصبح سليمة، تنتقل حركة المرور تدريجيًا إلى الحاوية الجديدة
- يتم إنهاء الحاويات القديمة بعد الانتهاء من طلباتها الحالية
يتولى Kubernetes الإيقاف التدريجي وتحويل حركة المرور تلقائيًا. يحتاج خط الأنابيب الخاص بك فقط إلى تحديث بيان النشر (deployment manifest) بعلامة الصورة الجديدة وتطبيقه.
الخطوة 4: تتبع ما هو قيد التشغيل
بعد النشر، يجب على خط الأنابيب الخاص بك تسجيل الإصدار قيد التشغيل. قم بتخزين هاش الالتزام (commit hash) أو علامة الصورة أو طابع النشر الزمني في مكان يسهل الوصول إليه. هذه المعلومات لا تقدر بثمن عندما تحتاج إلى:
- العودة إلى إصدار سابق
- التحقق من أي نشر أدخل خطأ
- ربط مشكلات الأداء بإصدارات محددة
نهج بسيط: قم بتوسيم صور Docker الخاصة بك بهاش الالتزام وقم بتخزين التعيين في قاعدة بيانات أو ملف نصي بسيط. يمكن لأدوات المراقبة الخاصة بك بعد ذلك الرجوع إلى هذه البيانات عند التنبيه.
قائمة التحقق العملية لخط أنابيب SSR الخاص بك
قبل أن تعتبر خط الأنابيب الخاص بك جاهزًا للإنتاج، تحقق من هذه النقاط:
- يتم تعبئة مخرجات البناء في قطعة برمجية قابلة للنشر (صورة Docker أو حزمة خادم)
- نقطة نهاية فحص الصحة موجودة وتعيد حالة ذات معنى
- ينتظر خط الأنابيب حتى ينجح فحص الصحة قبل توجيه حركة المرور
- يتوقف خط الأنابيب ويُرسل تنبيهًا إذا فشل فحص الصحة
- تم تكوين الإيقاف التدريجي (العملية القديمة تنهي الطلبات الجارية)
- تم اختبار استراتيجية التحديث الدوري (لا يوجد توقف أثناء النشر)
- يتم تخزين معلومات الإصدار وجعلها قابلة للوصول بعد النشر
- عملية العودة إلى الإصدار السابق موثقة ومختبرة
الخلاصة
الواجهة الأمامية SSR ليست موقعًا ثابتًا. إنها تطبيق خادم يصادف أنه يُصدر HTML. تعامل مع خط الأنابيب الخاص بك وفقًا لذلك: ابنِ لوقت التشغيل، وتحقق بفحوصات الصحة، وانشر باستراتيجيات بدون توقف، واعرف دائمًا أي إصدار يخدم المستخدمين. عندما تتقن هذه الأساسيات، لن يرى المستخدمون الشاشة الفارغة أبدًا. سيرون فقط صفحة سريعة وفعالة.