النشر والاستضافة
يتضمن نشر تطبيقات Next.js فهم عمليات البناء، ومنصات الاستضافة، وتكوين البيئة، وتقنيات التحسين. يغطي هذا الدرس كل شيء من النشر على Vercel إلى الاستضافة الذاتية باستخدام Docker.
فهم عملية البناء في Next.js
قبل النشر، تحتاج إلى فهم ما يحدث أثناء عملية البناء:
# وضع التطوير - إعادة تحميل ساخنة، غير محسّن
npm run dev
# بناء الإنتاج - ملفات ثابتة محسّنة
npm run build
# معاينة بناء الإنتاج محليًا
npm run start
تُنتج عملية البناء عدة مخرجات:
.next/
├── cache/ # ذاكرة التخزين المؤقت للبناء لإعادة البناء الأسرع
├── server/ # كود جانب الخادم ومسارات API
├── static/ # الأصول الثابتة مع تجزئات المحتوى
└── BUILD_ID # معرف بناء فريد
النشر على Vercel
Vercel هي المنصة الموصى بها لـ Next.js، وتوفر تكاملاً سلساً وأداءً مثالياً:
لماذا Vercel لـ Next.js؟ تم إنشاء Vercel بواسطة فريق Next.js، وتوفر التحسين التلقائي، والتخزين المؤقت على الحافة، والوظائف بدون خادم، ونشر المعاينة خارج الصندوق.
الطريقة 1: تكامل GitHub (موصى به)
# 1. ادفع كودك إلى GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/repo.git
git push -u origin main
# 2. الاتصال بـ Vercel
# - قم بزيارة vercel.com وسجل الدخول باستخدام GitHub
# - استورد مستودعك
# - قم بتكوين إعدادات المشروع
# - انشر تلقائيًا
الطريقة 2: واجهة سطر أوامر Vercel
# تثبيت واجهة سطر أوامر Vercel
npm i -g vercel
# تسجيل الدخول إلى Vercel
vercel login
# النشر للمعاينة
vercel
# النشر للإنتاج
vercel --prod
متغيرات البيئة في Vercel
قم بتكوين متغيرات البيئة من خلال لوحة التحكم أو واجهة سطر الأوامر:
// في إعدادات مشروع Vercel الخاص بك:
// Environment Variables → Add new
DATABASE_URL=postgresql://...
NEXT_PUBLIC_API_URL=https://api.example.com
SECRET_KEY=your-secret-here
// عبر واجهة سطر الأوامر
vercel env add DATABASE_URL
vercel env add NEXT_PUBLIC_API_URL
بادئات متغيرات البيئة: فقط المتغيرات التي تبدأ بـ NEXT_PUBLIC_ يتم عرضها في المتصفح. لا تبدأ أبدًا الأسرار بـ NEXT_PUBLIC_!
الاستضافة الذاتية مع Node.js
يمكنك استضافة Next.js على أي خادم Node.js (VPS، AWS EC2، DigitalOcean، إلخ):
الإعداد الأساسي
# بناء التطبيق
npm run build
# بدء خادم الإنتاج
NODE_ENV=production npm start
# مع منفذ مخصص
PORT=3000 npm start
استخدام PM2 لإدارة العمليات
# تثبيت PM2 عالميًا
npm install -g pm2
# بدء التطبيق مع PM2
pm2 start npm --name "nextjs-app" -- start
# التكوين مع ملف النظام البيئي
// ecosystem.config.js
module.exports = {
apps: [{
name: 'nextjs-app',
script: 'npm',
args: 'start',
env: {
NODE_ENV: 'production',
PORT: 3000
},
instances: 'max',
exec_mode: 'cluster',
max_memory_restart: '1G'
}]
};
# البدء مع التكوين
pm2 start ecosystem.config.js
# أوامر PM2 الأخرى
pm2 list # سرد جميع العمليات
pm2 logs nextjs-app # عرض السجلات
pm2 restart nextjs-app
pm2 stop nextjs-app
pm2 delete nextjs-app
نشر Docker
احتوِ تطبيق Next.js الخاص بك لعمليات نشر متسقة:
Dockerfile متعدد المراحل (محسّن)
# Dockerfile
FROM node:18-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
تكوين المخرجات المستقلة
قم بتمكين المخرجات المستقلة لصور Docker أصغر:
// next.config.js
module.exports = {
output: 'standalone',
};
Docker Compose للتطوير
# docker-compose.yml
version: '3.8'
services:
nextjs:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
# البناء والتشغيل
docker-compose up --build
تحسين البناء
قم بتحسين البناء الخاص بك للإنتاج:
تحليل الحزمة
# تثبيت محلل الحزمة
npm install @next/bundle-analyzer
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// التكوين الحالي الخاص بك
});
# تحليل الحزمة
ANALYZE=true npm run build
تكوين تقسيم الكود
// الاستيرادات الديناميكية لتقسيم الكود
import dynamic from 'next/dynamic';
// تحميل كسول للمكونات الثقيلة
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <p>جاري التحميل...</p>,
ssr: false // تعطيل SSR لهذا المكون
});
// تحميل مسبق للمكونات الحرجة
const CriticalComponent = dynamic(() => import('./Critical'), {
loading: () => <p>جاري التحميل...</p>
});
إعدادات تحسين الصور
// next.config.js
module.exports = {
images: {
domains: ['example.com', 'cdn.example.com'],
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60,
dangerouslyAllowSVG: false,
},
};
نشر التوليد الثابت للموقع (SSG)
للمواقع الثابتة بالكامل، قم بالتصدير إلى HTML ثابت:
// next.config.js
module.exports = {
output: 'export',
images: {
unoptimized: true // مطلوب للتصدير الثابت
}
};
# بناء موقع ثابت
npm run build
# دليل الإخراج
out/
├── index.html
├── about.html
├── _next/
└── ...
# النشر على استضافة ثابتة
# - Netlify
# - GitHub Pages
# - AWS S3 + CloudFront
# - Cloudflare Pages
استراتيجية CDN والتخزين المؤقت
قم بتنفيذ التخزين المؤقت الفعال للحصول على أداء مثالي:
تكوين رؤوس التخزين المؤقت
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, s-maxage=10, stale-while-revalidate=59'
}
]
},
{
source: '/:all*(svg|jpg|png|webp|avif)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable'
}
]
}
];
}
};
استراتيجية ISR (التجديد الثابت التدريجي)
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
export const revalidate = 3600; // إعادة التحقق كل ساعة
export default async function Post({ params }) {
const post = await getPost(params.slug);
return <article>{post.content}</article>;
}
أفضل ممارسات تكوين البيئة
قم بإدارة البيئات بفعالية عبر التطوير والتدريج والإنتاج:
هيكل ملفات البيئة
.env.local # التطوير المحلي (متجاهل من git)
.env.development # افتراضيات التطوير
.env.production # افتراضيات الإنتاج
.env.test # بيئة الاختبار
# مثال .env.local
DATABASE_URL=postgresql://localhost:5432/dev
NEXT_PUBLIC_API_URL=http://localhost:3000/api
SECRET_KEY=dev-secret-key
# مثال .env.production
DATABASE_URL=${{ secrets.DATABASE_URL }}
NEXT_PUBLIC_API_URL=https://api.production.com
SECRET_KEY=${{ secrets.SECRET_KEY }}
تكوين وقت التشغيل
// lib/config.ts
export const config = {
apiUrl: process.env.NEXT_PUBLIC_API_URL,
isDev: process.env.NODE_ENV === 'development',
isProd: process.env.NODE_ENV === 'production',
};
// الاستخدام في المكونات
import { config } from '@/lib/config';
export default function Component() {
const apiUrl = config.apiUrl;
// ...
}
المراقبة وتتبع الأخطاء
قم بتنفيذ المراقبة لتطبيقات الإنتاج:
تكامل Sentry
# تثبيت Sentry
npm install @sentry/nextjs
# تهيئة Sentry
npx @sentry/wizard -i nextjs
// sentry.client.config.js
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
});
// sentry.server.config.js
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});
خط أنابيب CI/CD
قم بأتمتة النشر باستخدام GitHub Actions:
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
NEXT_PUBLIC_API_URL: ${{ secrets.API_URL }}
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: '--prod'
تمرين: انشر تطبيقك
- قم بإعداد متغيرات البيئة للتطوير والإنتاج
- قم بإنشاء Dockerfile لتطبيق Next.js الخاص بك
- انشر على Vercel باستخدام تكامل GitHub
- قم بتكوين نطاق مخصص وشهادة SSL
- قم بتنفيذ ISR لصفحة مدونة مع إعادة التحقق لمدة ساعة واحدة
- قم بإعداد Sentry لتتبع الأخطاء
- قم بإنشاء سير عمل GitHub Actions للنشر التلقائي
- قم بتحليل حجم الحزمة الخاصة بك وتحسين الاستيرادات الثقيلة
قائمة التحقق من الإنتاج: قبل النشر، تأكد من تعيين جميع متغيرات البيئة، وتكوين تتبع الأخطاء، وتمكين رؤوس الأمان، وتحسين الصور، وأن لديك استراتيجية للتراجع.