استضافة Next.js ذاتيًا وما الذي يتوقّف عن العمل
يعمل Next.js حيث يعمل Node. وأربع ميزات تقدّمها المنصّة لا الإطار، ومعرفة أيّها الأربع هي الفرق بين ترحيل هادئ وآخر مليء بالمفاجآت.
لسؤال «هل نستطيع تشغيل هذا على بنيتنا التحتية؟» جوابان: قصير وطويل. القصير
نعم: next start خادم Node، ويعمل على جهاز افتراضي، وداخل حاوية، وخلف موازن
الحمل عندك، وفي منطقتك.
والطويل أن أربعة أشياء يظنّها الناس ميزات في Next.js تقدّمها في الحقيقة منصّة الاستضافة، وهي الأربعة نفسها التي تفاجئ الفرق بعد أسبوع من الترحيل.
البناء القابل للنشر فعلًا
البناء الافتراضي يترك لك مجلّد .next يحتاج شجرة node_modules كاملة إلى
جانبه. وبالنسبة لحاوية، تلك مئات الميغابايتات من اعتماديات لا تشغّلها.
// next.config.ts
export default {
output: 'standalone',
};هذا يتتبّع الوحدات التي يصل إليها الخادم فعلًا وينسخها إلى
.next/standalone، مع server.js يقلع بلا مدير حزم. في الشيفرات التي نقلناها
هبطت الصورة من نحو 1.2 غيغابايت إلى نحو 180 ميغابايت.
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:22-alpine AS run
WORKDIR /app
ENV NODE_ENV=production
# الأصول الثابتة و public/ ليست داخل standalone. نسخها هو الخطوة التي
# تُنسى، وعَرَضها موقع بلا CSS.
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]أمران في هذا الملف يستحقّان التصريح. .next/static وpublic/ ليسا جزءًا من
مخرجات standalone ويجب نسخهما على حدة - وإن فاتاك، قدّم النشر HTML بلا CSS
وبلا صور. وnpm run build يعمل وقت بناء الصورة، فكل متغيّر بيئة تقرأه شيفرتك
على مستوى الوحدة يجب أن يكون موجودًا حينها، لا وقت التشغيل فقط.
الأشياء الأربعة التي كانت المنصّة تؤدّيها
تحسين الصور. يحتاج next/image إلى ما يغيّر الأبعاد ويعيد الترميز. على
المنصّة هذه خدمة؛ وعلى خادمك هي sharp، داخل عمليّتك، وعلى معالجك.
npm install sharpثبّتها وتُستعمَل تلقائيًا. وإن جعل حجم زياراتك كلفة المعالج حقيقية، فوجّه
images.loader إلى شبكة توزيع تغيّر الأبعاد، أو ولّد المقاسات مسبقًا وقت
البناء. وما يجب ألّا تفعله هو ترك images.unoptimized: true في الإعدادات
ونسيانه - فذلك يرسل الملف الأصلي إلى كل زائر ويُبطِل بصمت سبب استعمالك
المكوّن أصلًا.
الـ ISR وذاكرة إعادة التحقّق. على حاوية واحدة ينجح هذا: الذاكرة على القرص
المحلّي. وعلى ثلاث حاويات خلف موازن حمل لا ينجح - لكلٍّ قرصها، وrevalidateTag
تمسح الذاكرة على النسخة التي تلقّت الاستدعاء، وتظلّ الأخريان تقدّمان الصفحة
القديمة حتى تعيدا التحقّق مصادفةً. والحلّ معالج ذاكرة مشترك:
// next.config.ts
export default {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // عطّل الـ LRU داخل العملية؛ Redis هو المصدر
};أي معالج يعتمد على Redis يفي بالغرض. المهم فهم لماذا هو ضروري، وإلا بدت عبارة «تحدّثت الصفحة لبعض المستخدمين دون بعض» خللًا مستحيلًا. ومعرفة أي ذاكرة تفعل ماذا تستحقّ القراءة: الطبقات الأربع وأيّها أوقعك.
الوسيط على الحافة. لم يعد وسيطك يعمل في مئة موقع قبل أن يصل الطلب إلى خادم؛ صار يعمل في خادمك، في منطقتك الواحدة. والشيفرة المكتوبة على افتراض أنه شبه مجاني - بحث جغرافي، أو توزيع اختبار أ/ب - صارت الآن في المسار الحرج لكل طلب. تلك كلفة حقيقية تستحقّ القياس لا الافتراض.
التدفّق عبر وكيلك. يرسل Suspense وloading.tsx الاستجابة على أجزاء. وnginx
أمامك بالإعدادات الافتراضية يخزّن الاستجابة كاملة قبل إرسالها، فيحوّل التدفّق
إلى نسخة أبطأ من عدم التدفّق، بلا أي خطأ يخبرك.
location / {
proxy_pass http://app:3000;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
}ما تكسبه
ليست الكلفة وحدها، وإن كان فرقها عند الحجم كبيرًا. تحصل على بياناتك في ولاية قضائية اخترتها، وهو أمر غير قابل للتفاوض لعميل لديه اشتراط تركي أو أوروبي بشأن موطن البيانات. وتستطيع العمل في الشبكة نفسها التي فيها قاعدة بياناتك، فتحذف رحلة ذهاب وإياب من كل استعلام. وتحصل على نشر لا يغيّره من تحتك قرار تسعير يخصّ غيرك.
ما تدفعه
صارت الجاهزية مسؤولية أحدهم. ونسخ المعاينة لكل طلب دمج، والتراجع الفوري، وشبكة توزيع عالمية، كلّها عمل حقيقي لإعادة بنائه، والفريق الذي لم يشغّل بنية تحتية قطّ سيقضي الشهر الأول يكتشف من جديد لماذا وُجدت تلك الميزات.
قاعدتنا التقريبية: إن كان التطبيق في منطقة واحدة، أو كان لدى الفريق خدمات يشغّلها أصلًا، أو كان هناك اشتراط بشأن موطن البيانات، فالاستضافة الذاتية صحيحة ببساطة. وإن كان موقعًا تسويقيًا بمهندسَين وزيارات عالمية، فالمنصّة أرخص من راتب من سيصون البديل.
في الحالتين، اتّخذ القرار على هذه الأسس لا على قياس أداء. فالإطار يعمل بالطريقة نفسها في الموضعين - الذي يتغيّر هو الميزات الأربع أعلاه.
