دليل النشر

نشر تطبيق Next.js على VPS

انشر على VPS Cloud ←

دليل عملي

نشر تطبيق Next.js على VPS

التطوير13 دقيقةً للقراءةعدد الخطوات: 6

يجمع Next.js بين التصيير من جهة الخادم والتوليد الثابت ومسارات API في إطار React واحد. ونشره على VPS بدلًا من منصة احتكارية يحرّرك من حصص الدوال وحدود عرض النطاق (bandwidth) والارتباط بمزوّد واحد، مع إبقاء SSR يعمل بكامل طاقته.

المحتويات· لماذا تستضيف Next‎.js ذاتيًا على VPS؟1/14
  1. 01لماذا تستضيف Next‎.js ذاتيًا على VPS؟
  2. 02فوائد ملموسة لاستضافة Next‎.js ذاتيًا
  3. 03المتطلبات المسبقة للعتاد والبرمجيات
  4. 04بناء Docker متعدد المراحل: node:20-alpine
  5. 05متغيرات البيئة: ‎.env‎.local مقابل ‎.env‎.production
  6. 06نشر Next‎.js خطوة بخطوة
  7. 07إعداد Nginx الكامل مع upstream
  8. 08استراتيجية ISR: إعادة التحقق وثبات الذاكرة المؤقتة
  9. 09مكوّنات الخادم مقابل مكوّنات العميل: تأثير ذاكرة RAM والمعالج
  10. 10CI/CD: GitHub Actions أو Forgejo
  11. 11المراقبة مع PM2
  12. 12استكشاف الأخطاء: أخطاء شائعة في الإنتاج
  13. 13النسخ الاحتياطي لـ ‎.next/cache
  14. 14نشر Next‎.js بنقرة واحدة من Marketplace

لماذا تستضيف Next‎.js ذاتيًا على VPS؟

غالبًا ما يُقرَن Next‎.js بمنصة استضافة بعينها، لكن خادم Node‎.js المستقل (standalone) الخاص به يعمل بشكل مثالي على أي VPS. وتصبح الاستضافة الذاتية مجدية بمجرد استخدامك المكثف لـSSR أو ISR (التوليد الثابت التزايدي) أو مسارات API: فهذه الميزات تستهلك استدعاءات مفوترة على المنصات المُدارة، بينما هي مجانية وغير محدودة على خادمك. تتحكم في ذاكرة ISR المؤقتة على القرص، وفي عرض النطاق للصور المُحسَّنة، وفي زمن تنفيذ الدوال، دون حد الـ10 ثوانٍ.

فوائد ملموسة لاستضافة Next‎.js ذاتيًا

  • SSR ومسارات API دون حصة استدعاءات ودون فوترة لكل دالة.
  • ذاكرة ISR مؤقتة دائمة على القرص، دون فقدان إعادة التحقق بين عمليات النشر.
  • عرض نطاق مشمول، مثالي للمواقع الغنية بالصور والفيديو.
  • عدة مشاريع Next‎.js على VPS واحد، موحَّدة تحت Nginx.
  • تحسين الصور عبر next/image يُقدَّم محليًا دون تكلفة إضافية لكل تحويل.
  • بناء ونشر مُتحكَّم فيهما عبر Git أو CI/CD أو مجرد git pull وإعادة بناء.

المتطلبات المسبقة للعتاد والبرمجيات

عملية بناء Next‎.js نهِمة للذاكرة: خصّص ما لا يقل عن 2 غيغابايت من ذاكرة RAM (و4 غيغابايت لمشروع كبير بكثير من الصفحات)، وإلا فقد تفشل عملية البناء بسبب نقص الذاكرة. أما من ناحية وقت التشغيل، فيكفي 1 إلى 2 vCPU لتقديم SSR. ثبّت Node‎.js 18 أو 20 LTS، إما أصليًا عبر nvm أو عبر صورة Docker node:20-alpine. فعّل output: 'standalone' في next‎.config‎.js لنشر خفيف.

بناء Docker متعدد المراحل: node:20-alpine

يُقلّص البناء متعدد المراحل الصورة النهائية إلى الحد الأدنى ويتجنّب شحن أدوات البناء إلى بيئة الإنتاج. تعتمد الاستراتيجية الثلاثية المراحل — deps وbuilder وrunner — وهي الأكثر شيوعًا مع Next‎.js في وضع standalone.

# المرحلة 1 — الاعتماديات
FROM node:20-alpine AS deps
WORKDIR /app
COPY package‎.json package-lock‎.json ./
RUN npm ci --omit=dev

# المرحلة 2 — البناء
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# المرحلة 3 — المشغّل (الصورة النهائية)
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/‎.next/standalone ./
COPY --from=builder /app/‎.next/static ./‎.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server‎.js"]

تُثبّت مرحلة deps الاعتماديات الإنتاجية فقط (--omit=dev). تنسخ مرحلة builder المصدر الكامل وتُشغّل npm run build. لا تحتوي مرحلة runner إلا على مجلد standalone الذي يُنشئه Next‎.js والأصول الثابتة ومجلد public — بلا node_modules مصدرية.

متغيرات البيئة: ‎.env‎.local مقابل ‎.env‎.production

يُميّز Next‎.js بين عائلتين من المتغيرات بحسب نطاقهما.

المتغيرات العامة (NEXT_PUBLIC_*): تُدمَج في حزمة JavaScript وقت البناء وتُكشَف للمتصفح. تناسب URL واجهة برمجة عامة أو معرّف Google Analytics أو علامة ميزة. لا تضع فيها أسرارًا أبدًا.

متغيرات الخادم: تُقرَأ على جانب Node فقط (مسارات API ومكوّنات الخادم وgetServerSideProps). لا تُرسَل إلى العميل أبدًا. هنا تعيش مفاتيح API الخارجية وسلاسل اتصال قاعدة البيانات وأسرار JWT.

على VPS، نهجان متاحان: حقن المتغيرات في بيئة عملية PM2 عبر ملف النظام البيئي (ecosystem‎.config‎.js)، أو تمريرها إلى Docker عبر --env-file ‎.env‎.production. النهج الثاني أفضل: يبقى الملف على قرص الخادم خارج مستودع git.

تنبيه: يجب أن تكون متغيرات NEXT_PUBLIC_* معروفة وقت البناء، وليس فقط وقت التشغيل. إذا غيّرت متغيرًا عامًا بعد البناء، يجب إعادة بناء التطبيق.

نشر Next‎.js خطوة بخطوة

  1. تجهيز الخادم

    عبر SSH، ثبّت Node‎.js 20 LTS وPM2 (npm install -g pm2)، أو Docker. استنسخ المستودع وأنشئ ‎.env‎.production مع متغيراتك (NEXT_PUBLIC_* للعميل، وأسرار الخادم لمسارات API).

  2. بناء التطبيق

    نفّذ npm ci ثم npm run build. ومع output: 'standalone'، يُنشئ Next‎.js مجلدًا مستقلًا ‎.next/standalone يحتوي فقط على الاعتماديات اللازمة، ما يخفّف الصورة بشكل كبير.

  3. تشغيل خادم Node

    شغّل الخادم باستخدام pm2 start node --name nextjs -- ‎.next/standalone/server‎.js على المنفذ 3000، أو عبر حاوية Docker. اضبط pm2 startup وpm2 save لإعادة تشغيل تلقائية عند إعادة إقلاع VPS.

  4. إعداد Nginx في الواجهة الأمامية

    أنشئ كتلة خادم تنفّذ proxy_pass http://localhost:3000، وتُمرّر ترويستَي Host وX-Forwarded-For، وتقدّم /_next/static/ مباشرة من القرص لتخفيف العبء عن Node. فعّل ضغط gzip.

  5. تثبيت شهادة SSL

    احصل على شهادة Let's Encrypt عبر Certbot لـyourdomain‎.com، وافرض إعادة التوجيه إلى HTTPS، واضبط التجديد التلقائي. تحقّق من تمرير ترويسات X-Forwarded-Proto بشكل صحيح لأجل SSR.

  6. إعداد عمليات النشر

    أتمِت دورة git pull && npm ci && npm run build && pm2 reload nextjs عبر سكربت أو webhook خاص بـGit. ويضمن أمر reload في PM2 إعادة تشغيل دون انقطاع (zero-downtime) بين إصدارين.

إعداد Nginx الكامل مع upstream

يتجاوز إعداد Nginx الكامل لـNext‎.js مجرد proxy_pass. تحتاج إلى تقديم الأصول الثابتة مباشرة من القرص، وإدارة ترويسات الذاكرة المؤقتة، وتفعيل الضغط، وتمرير معلومات العميل بشكل صحيح.

upstream nextjs_upstream {
  server 127.0.0.1:3000;
  keepalive 64;
}

server {
  listen 443 ssl http2;
  server_name yourdomain‎.com;

  gzip on;
  gzip_types text/plain text/css application/javascript application/json image/svg+xml;

  location /_next/static/ {
    alias /home/deploy/myapp/‎.next/static/;
    expires 1y;
    add_header Cache-Control "public, immutable";
  }

  location / {
    proxy_pass http://nextjs_upstream;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

تُحافظ كتلة upstream مع keepalive 64 على مجمع اتصالات دائمة نحو Node، ما يتجنّب التفاوض على TCP في كل طلب. توجيه proxy_http_version 1.1 ضروري لعمل اتصالات keepalive فعليًا.

استراتيجية ISR: إعادة التحقق وثبات الذاكرة المؤقتة

يتيح ISR (التوليد الثابت التزايدي) لـNext‎.js إعادة توليد الصفحة الثابتة في الخلفية بعد تأخير معيّن، دون إعادة بناء كاملة. على VPS، يتطلّب هذا بقاء الذاكرة المؤقتة عبر عمليات إعادة التشغيل.

تُخزَّن ذاكرة ISR المؤقتة في ‎.next/cache. خياران متاحان لجعلها تنجو من عمليات إعادة النشر:

الخيار 1 — وحدة تخزين دائمة: ربط ‎.next/cache خارج مجلد النشر وإعادة نسخها بعد كل rebuild.

الخيار 2 — معالج ذاكرة مؤقتة Redis: لعدة نسخ Node أو احتياج المشاركة بين الأجهزة، يدعم Next‎.js معالجات الذاكرة المؤقتة المخصّصة منذ الإصدار 13.4. يتيح هذا نقل ذاكرة ISR المؤقتة إلى Redis.

للمواقع ذات الحركة المنخفضة، يكفي الخيار 1. يصبح الخيار 2 ضروريًا عند وجود عدة عمليات Node (مجموعة PM2) أو عدة VPS خلف موازن حِمل.

مكوّنات الخادم مقابل مكوّنات العميل: تأثير ذاكرة RAM والمعالج

منذ Next‎.js 13 وApp Router، المكوّنات هي مكوّنات خادم بشكل افتراضي. للتمييز تبعات مباشرة على استهلاك موارد VPS.

مكوّنات الخادم تعمل على جانب الخادم فقط. يمكنها قراءة قاعدة البيانات مباشرة والوصول إلى نظام الملفات، ولا تُرسَل قط إلى حزمة JavaScript للمتصفح. والنتيجة HTML خالص يُقلّص حجم حزمة العميل ويُحسّن Core Web Vitals (LCP). على الخادم، تستهلك CPU في كل طلب SSR غير مُخزَّن مؤقتًا.

مكوّنات العميل ('use client' في أعلى الملف) يتم ترطيبها في المتصفح. ضرورية للتفاعلات: أحداث، حالة محلية، hooks (useState، useEffect).

القاعدة العملية على VPS: احتفظ بمكوّنات الخادم لكل ما يتعلق بالبيانات، وحدّد مكوّنات العميل في مناطق التفاعل.

CI/CD: GitHub Actions أو Forgejo

يتجنّب أتمتة النشر الأخطاء البشرية ويضمن أن كل دمج على الفرع الرئيسي يُشغّل إعادة بناء نظيفة. حلّان شائعان على VPS: GitHub Actions (إذا كان مستودعك على GitHub) وForgejo (منصة مستضافة ذاتيًا، بديل مفتوح المصدر لـGitHub/Gitea).

name: Deploy Next‎.js
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.VPS_HOST }}
          username: deploy
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /home/deploy/myapp
            git pull origin main
            npm ci
            npm run build
            pm2 reload nextjs

في كلتا الحالتين، تُضبَط الأسرار (مفتاح SSH، متغيرات البيئة) في أسرار المستودع ولا تظهر أبدًا في السجلات.

المراقبة مع PM2

PM2 هو مدير العمليات وأداة المراقبة الأولى لتطبيق Next‎.js. أوامر أساسية:

# حالة العمليات
pm2 list

# سجلات مباشرة
pm2 logs nextjs

# مقاييس CPU وذاكرة RAM
pm2 monit

# إعادة تشغيل بلا انقطاع
pm2 reload nextjs

فعّل pm2-logrotate لمنع امتلاء القرص بملفات السجل:

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7

احفظ قائمة العمليات بعد كل تغيير: pm2 save.

إذا كنت تستخدم ISR، فاربط وحدة تخزين دائمة لمجلد ‎.next/cache كي تبقى الصفحات المُعاد التحقق منها بعد عمليات إعادة النشر. وبدون ذلك، تبدأ كل عملية إعادة بناء من ذاكرة مؤقتة فارغة وتسبّب ذروة توليد فوري. ولعدة نسخ Node خلف موازن حِمل، انقل هذه الذاكرة المؤقتة إلى تخزين مشترك أو إلى Redis مع معالِج ذاكرة مؤقتة مخصّص.

استكشاف الأخطاء: أخطاء شائعة في الإنتاج

تتكرر ثلاثة إلى خمسة أخطاء بشكل منتظم عند أول نشر لتطبيق Next‎.js على VPS.

ENOMEM أثناء npm run build
يُجري بناء Next‎.js التجميع بالتوازي وقد يتجاوز 2 غيغابايت من ذاكرة RAM. إذا توقف البناء بـKilled أو JavaScript heap out of memory، ارفع حد الذاكرة:

NODE_OPTIONS="--max-old-space-size=4096" npm run build

Port 3000 already in use
عملية PM2 قديمة أو عملية Node يتيمة تستمع بالفعل على المنفذ 3000. حدّدها وأوقفها:

lsof -i :3000
kill -9 <PID>

MODULE_NOT_FOUND في الإنتاج مع output: 'standalone'
مجلد ‎.next/standalone يحتوي نسخة من الاعتماديات اللازمة، لكن ليس الأصول الثابتة ولا مجلد public. انسخ المجلدات الثلاثة:

cp -r ‎.next/static ‎.next/standalone/‎.next/static
cp -r public ‎.next/standalone/public

حلقة إعادة توجيه HTTPS مع X-Forwarded-Proto
تأكد أن Nginx يُمرّر X-Forwarded-Proto: https وأن تطبيقك يقرأ هذه الترويسة لتحديد البروتوكول الفعلي.

النسخ الاحتياطي لـ ‎.next/cache

يحتوي مجلد ‎.next/cache على نوعين من البيانات القيّمة: الصفحات ISR المُعاد التحقق منها وذاكرة تجميع Webpack/SWC المؤقتة. فقدان هذه الذاكرة يُجبر Next‎.js على إعادة توليد جميع صفحات ISR فور أول طلب.

أعدّ نسخة احتياطية بسيطة باستخدام rsync أو tar قبل كل نشر. ذاكرة Webpack المؤقتة تُسرّع عمليات إعادة البناء اللاحقة بشكل ملحوظ — على مشروع متوسط، تستغرق إعادة البناء مع ذاكرة مؤقتة كاملة 40 إلى 60 بالمئة أقل من البناء الأولى.

نشر Next‎.js بنقرة واحدة من Marketplace

يوفّر Marketplace من ServOrbit قالب Next‎.js Stack الذي يُهيّئ تلقائيًا Node‎.js LTS وPM2 وNginx وPostgreSQL على خادمك الافتراضي. في دقائق قليلة، ستكون بيئة الإنتاج الخاصة بك جاهزة لاستقبال تطبيق React SSR الخاص بك — دون أي إعداد يدوي.

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

بيئة Next.js جاهزة في دقائق

يُهيّئ قالب Next.js Stack تلقائيًا Node.js LTS وPM2 وNginx وPostgreSQL — جاهزًا لاستقبال تطبيق React SSR الخاص بك.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة