Next.js: المشروع النهائي: النشر و CI/CD
آخر تحديث: 2026-08-26
من التزام الكود إلى متصفح المستخدم، هناك عدة خطوات بينهما — النشر، وCI/CD، والمراقبة، وتحسين الأداء — وهذه هي الخطوة الأخيرة لجعل تطبيقك "حيا" حقا.
1. ما ستتعلمه
- عملية نشر Vercel الكاملة (vercel.json + PostgreSQL + نطاق مخصص + environment variables)
- حل Docker للنشر الذاتي (بناء Dockerfile متعدد المراحل + docker-compose.yml + Nginx + PM2)
- خط أنابيب GitHub Actions CI/CD (lint → test → build → deploy → Lighthouse CI)
- تتبع أحداث PostHog + @vercel/speed-insights + مراقبة أخطاء Sentry
- تحسين الأداء العملي (Lighthouse 90+/100+ next/image lazy loading + تحليل الحزمة)
- ملخص مسار تعلم Next.js 16 الكامل والاتجاهات المتقدمة
2. قصة حقيقية لمهندس DevOps
(1) نقطة الألم: كل عملية نشر تشبه "الدوس على لغم أرضي"
ديانا هي مهندسة DevOps في شركة Acme Corp، مسؤولة عن نشر وتشغيل TaskFlow. ينشر الفريق 20 مرة شهريا، لكن كل عملية نشر تجربة مرهقة للأعصاب: رفع الكود يدويا عبر SSH أدى إلى فقدان environment variables (مما جعل قاعدة بيانات production غير قابلة للوصول)؛ npm run build — كان يعمل محليا لكنه تسبب في خطأ OOM (نفاد الذاكرة) على الخادم؛ أخطاء المستخدمين لم تكتشف إلا بعد ساعتين من النشر (بسبب نقص تنبيهات المراقبة)؛ ولم يلاحظ أحد أن درجة Lighthouse انخفضت من 85 إلى 62. تسبب آخر نشر في انقطاع لمدة 30 دقيقة، مما أدى إلى أكثر من 200 شكوى لخدمة العملاء.
(2) حل CI/CD الآلي + النشر المزدوج + المراقبة
أتمتة فحوصات الجودة مع GitHub Actions + نشر بدون إعداد مع Vercel + بدائل Docker للنشر الذاتي + مراقبة شاملة مع PostHog/Sentry.
# سطر واحد من GitHub Actions يشغل النشر الآلي بالكامل
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: amondnet/vercel-action@v20
(3) المكاسب
| البعد | النشر اليدوي | أتمتة CI/CD |
|---|---|---|
| وقت النشر | 45 دقيقة (بما في ذلك الفحوصات اليدوية) | 8 دقائق (آلي بالكامل) |
| خطر الانقطاع | مرتفع (ملفات مفقودة/إعدادات خاطئة) | منخفض (اتساق مضمون) |
| اكتشاف المشكلات | شكوى مستخدم بعد ساعتين | تنبيه Sentry فوري |
| درجة Lighthouse | تشغيل يدوي مرة واحدة شهريا | اكتشاف تلقائي عند PR |
| سرعة التراجع | 15 دقيقة استعادة يدوية | دقيقة واحدة Vercel Rollback |
| كفاءة الفريق | اختناقات DevOps | نشر ذاتي الخدمة |
3. النشر على Vercel
(1) هندسة Vercel
graph TB
subgraph "شبكة Vercel الطرفية"
A[CDN عالمي] --> B[Edge Functions]
B --> C[Serverless Functions]
C --> D[Vercel Postgres]
end
subgraph "GitHub"
E[الكود المصدري] -->|Push| F[GitHub Actions]
F -->|نشر تلقائي| A
end
subgraph "المراقبة"
G[Vercel Analytics]
H[Sentry]
I[PostHog]
end
C --> G
C --> H
B --> I
style A fill:#cce5ff
style E fill:#d4edda
style F fill:#ffeeba
▶ مثال: إعداد vercel.json
المخرجات:
إعداد JSON مع المفاتيح: framework ("nextjs")، buildCommand، outputDirectory، installCommand، regions (iad1/hkg1/gru1)، env، crons، headers (رؤوس الأمان + قواعد التخزين المؤقت)، و redirects.
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"regions": ["iad1", "hkg1", "gru1"],
"env": {
"NEXT_PUBLIC_APP_URL": "https://taskflow.vercel.app"
},
"crons": [
{
"path": "/api/cron/daily-digest",
"schedule": "0 8 * * *"
}
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
}
]
},
{
"source": "/uploads/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
],
"redirects": [
{
"source": "/app",
"destination": "/dashboard",
"permanent": true
}
]
}
المخرجات:
تم تطبيق إعداد JSON بنجاح.
▶ مثال: النشر باستخدام Vercel CLI
المخرجات:
اكتمل الأمر.
# 1. تثبيت Vercel CLI
npm install -g vercel
# 2. تسجيل الدخول إلى Vercel
vercel login
# 3. ربط المشروع
vercel link
# 4. تعيين environment variables
vercel env add DATABASE_URL
vercel env add AUTH_SECRET
vercel env add GOOGLE_CLIENT_ID
vercel env add GOOGLE_CLIENT_SECRET
vercel env add AUTH_URL
vercel env add NEXT_PUBLIC_POSTHOG_KEY
vercel env add SENTRY_DSN
# 5. معاينة النشر
vercel
# 6. نشر production
vercel --prod
# 7. عرض سجل النشر
vercel logs
المخرجات:
added 127 packages in 3.2s
38 packages are looking for funding
run `npm fund` for details
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Environment variable set.
Vercel CLI 28.0.0
? Set up and deploy "C:\Users\admin\taskflow"? [Y/n] Y
? Which scope? Acme Corp
? Link to existing project? No
? What's your project's name? taskflow
? In which directory is your code? ./
Auto-detected Project Settings (Next.js):
- Build Command: npx next build
- Output Directory: .next
- Node.js Version: 20.x
✅ Production: https://taskflow.vercel.app [7s]
▶ مثال: الاتصال بـ Vercel Postgres
# 1. إنشاء قاعدة بيانات Postgres
vercel env add DATABASE_URL
# 2. تثبيت Vercel Postgres SDK
npm install @vercel/postgres
# 3. تحديث مصدر بيانات Prisma
// prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
// Vercel Postgres — إدارة تلقائية لتجمع الاتصالات
// على Vercel، قم بتمكين shadowDatabaseUrl لتجنب تعارضات الترحيل
}
المخرجات:
Prisma schema updated. Run npx prisma generate to sync client.
// src/lib/db.ts
import { PrismaClient } from "@prisma/client"
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma
4. Docker للنشر الذاتي
(1) هندسة النشر الذاتي
graph TB
subgraph "مضيف Docker"
A[Nginx<br/>وكيل عكسي] --> B[تطبيق Node.js<br/>(PM2)]
B --> C[PostgreSQL<br/>(حاوية)]
end
subgraph "خارجي"
D[DNS: taskflow.example.com]
end
D --> A
A -->|إنهاء SSL| B
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#f8d7da
▶ مثال: بناء متعدد المراحل في Dockerfile
المخرجات:
Sending build context to Docker daemon 4.096kB
Step 1/8 : FROM node:20-alpine AS deps
---> 1dd67de0f936
...
Successfully built a7b3c2d1e0f9
Successfully tagged taskflow:latest
# ============================================
# المرحلة 1: التبعيات
# ============================================
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production --ignore-scripts
RUN npm ci --only=development --ignore-scripts
# ============================================
# المرحلة 2: البناء
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
ENV NEXT_OUTPUT=standalone
RUN npx prisma generate
RUN npm run build
# ============================================
# المرحلة 3: تشغيل production
# ============================================
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
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
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
المخرجات:
Sending build context to Docker daemon 4.096kB
Step 1/8 : FROM node:20-alpine AS deps
---> 1dd67de0f936
...
Successfully built a7b3c2d1e0f9
Successfully tagged taskflow:latest
▶ مثال: docker-compose.yml
المخرجات:
احفظ إعداد YAML أعلاه في مسار الملف المحدد. ستدخل الإعدادات حيز التنفيذ عند إعادة تشغيل الخادم التالية.
version: "3.8"
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://taskflow:password@db:5432/taskflow
- AUTH_SECRET=${AUTH_SECRET}
- AUTH_URL=https://taskflow.example.com
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
- NEXTAUTH_URL=https://taskflow.example.com
- NODE_ENV=production
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- taskflow-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=taskflow
- POSTGRES_USER=taskflow
- POSTGRES_PASSWORD=${DB_PASSWORD}
ports:
- "5432:5432"
restart: unless-stopped
networks:
- taskflow-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U taskflow"]
interval: 10s
timeout: 5s
retries: 5
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
restart: unless-stopped
networks:
- taskflow-network
volumes:
postgres-data:
networks:
taskflow-network:
driver: bridge
المخرجات:
أقسام الإعداد: version، services، volumes، networks.
▶ مثال: إعداد Nginx
المخرجات:
الأقسام: version، services، volumes، networks.
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream taskflow_app {
server app:3000;
}
server {
listen 80;
server_name taskflow.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name taskflow.example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# رؤوس الأمان
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# ضغط Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;
gzip_min_length 1000;
gzip_comp_level 6;
# الموارد الثابتة (تخزين مؤقت دائم)
location /_next/static {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
expires 365d;
add_header Cache-Control "public, immutable";
}
# المرفوعات
location /uploads {
proxy_pass http://taskflow_app;
proxy_set_header Host $host;
expires 30d;
add_header Cache-Control "public, immutable";
}
# مسارات API (بدون تخزين مؤقت)
location /api {
proxy_pass http://taskflow_app;
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;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
# كل شيء آخر
location / {
proxy_pass http://taskflow_app;
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;
# دعم WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
المخرجات:
تم تطبيق إعداد Nginx. أعد التحميل للتفعيل.
5. GitHub Actions CI/CD
(1) هندسة خط الأنابيب
graph LR
A[Push إلى main] --> B[Lint]
B --> C[فحص الأنواع]
C --> D[اختبار الوحدة]
D --> E[Build]
E --> F[نشر إلى Vercel]
F --> G[Lighthouse CI]
G --> H{الدرجة >= 90؟}
H -->|نعم| I[نجاح]
H -->|لا| J[تراجع]
style A fill:#cce5ff
style F fill:#d4edda
style G fill:#ffeeba
style J fill:#f8d7da
6. مراقبة production
(1) هندسة المراقبة
graph TB
subgraph "مقاييس المستخدم"
A["PostHog<br/>الأحداث والمسارات"]
B["Vercel Speed Insights<br/>مراقبة المستخدم الحقيقي"]
end
subgraph "تتبع الأخطاء"
C["Sentry<br/>الأخطاء والأداء"]
end
subgraph "الأداء"
D["Lighthouse CI<br/>اتجاهات الدرجات"]
E["Bundle Analyzer<br/>حجم الحزمة"]
end
subgraph "التنبيهات"
F["تنبيهات Sentry<br/>PagerDuty"]
G["فحوصات GitHub<br/>تعليق PR"]
end
A --> F
B --> D
C --> F
D --> G
E --> G
style A fill:#d4edda
style B fill:#cce5ff
style C fill:#f8d7da
7. تحسين الأداء
(1) مقارنة استراتيجيات التحسين
| الاستراتيجية | المقياس | قبل التحسين | بعد التحسين | الأدوات |
|---|---|---|---|---|
| next/image lazy | LCP | 3.2s | 1.5s | <Image loading="lazy"> |
| تقسيم الحزمة | TTI | 4.5s | 2.8s | @next/bundle-analyzer |
| تحسين الخطوط | CLS | 0.25 | 0.02 | next/font display:swap |
| PPR Static Shell | FCP | 2.1s | 0.4s | experimental.ppr |
| CDN الصور | LCP | 2.8s | 1.2s | Vercel Image Optimization |
| استراتيجية التخزين المؤقت | TTFB | 800ms | 120ms | revalidateTag + CDN |
8. مثال كامل: النشر والتحقق في بيئة production
# ============================================
# عملية نشر TaskFlow الكاملة في production
# ============================================
# --- الخطة أ: نشر Vercel ---
# 1. فحوصات ما قبل البناء
npm run lint && npx tsc --noEmit && npm run test -- --run
# 2. البناء والتحقق
npm run build
# المخرجات: ✓ Compiled successfully in 12.8s
# 3. معاينة النشر
vercel
# المخرجات: https://taskflow-git-feature-abc123.vercel.app
# 4. تشغيل اختبار E2E
npx playwright test --url=https://taskflow-git-feature-abc123.vercel.app
# 5. فحص Lighthouse
npx lhci autorun
# 6. نشر production
vercel --prod
# المخرجات: https://taskflow.vercel.app (Production)
# 7. إعداد نطاق مخصص
vercel domains add taskflow.example.com
# المخرجات: ✓ Domain taskflow.example.com added
# 8. التحقق
curl -I https://taskflow.example.com/api/health
# المخرجات: HTTP/2 200
# --- الخطة ب: Docker للنشر الذاتي ---
# 1. بناء صورة Docker
docker build -t taskflow:latest .
# 2. بدء الخدمة
docker compose up -d
# 3. تشغيل ترحيل قاعدة البيانات
docker compose exec app npx prisma migrate deploy
# 4. تشغيل البيانات الأولية
docker compose exec app npx prisma db seed
# 5. التحقق
curl http://localhost/api/health
# المخرجات: {"status":"healthy","timestamp":"2026-07-06T10:00:00Z"}
# 6. عرض السجلات
docker compose logs -f app
# 7. مقاييس المراقبة
# - PostHog: https://app.posthog.com/project/taskflow
# - Sentry: https://sentry.io/organizations/acme/projects/taskflow
# - Vercel Dashboard: https://vercel.com/acme/taskflow
# --- التحقق من الأداء ---
# تقرير Lighthouse
# Performance: 94/100 ✅
# Accessibility: 97/100 ✅
# Best Practices: 93/100 ✅
# SEO: 100/100 ✅
# Core Web Vitals (RUM)
# LCP: 1.2s ✅ (الهدف < 2.5s)
# FID: 12ms ✅ (الهدف < 100ms)
# CLS: 0.02 ✅ (الهدف < 0.1)
9. مراجعة ومواضيع متقدمة في مسار التعلم
(1) خارطة طريق تعلم Next.js 16 الكامل
graph TB
subgraph "المرحلة 1: الأساسيات (6 دروس)"
A1["01-02: مقدمة + بيئة العمل"]
A2["03-04: التوجيه + التخطيط"]
A3["05-06: التنقل + المسارات المتوازية"]
end
subgraph "المرحلة 2: البيانات (7 دروس)"
B1["07-08: RSC + جمع البيانات"]
B2["09-10: SSG/ISR/PPR"]
B3["11-12: التخزين المؤقت + Server Actions"]
B4["13-14: Actions المتقدمة + API Routes"]
end
subgraph "المرحلة 3: متقدم (6 دروس)"
C1["15: المصادقة Auth.js"]
C2["16: قاعدة البيانات Prisma"]
C3["17: التدفق (Streaming)"]
C4["18: الصور/الخطوط"]
C5["19: SEO/Metadata"]
C6["20: i18n/Middleware"]
end
subgraph "المرحلة 4: production (6 دروس)"
D1["21-22: اختبار الوحدة + E2E"]
D2["23-24: CI/CD + Docker"]
D3["25-26: الأداء + الأمان/الترحيل"]
end
subgraph "المرحلة 5: مشاريع شاملة (4 دروس)"
E1["27: التهيئة + المصادقة"]
E2["28: لوحة التحكم + PPR"]
E3["29: CRUD + Server Actions"]
E4["30: النشر + CI/CD + المراقبة"]
end
A1 --> A2 --> A3 --> B1
B1 --> B2 --> B3 --> B4 --> C1
C1 --> C2 --> C3 --> C4 --> C5 --> C6 --> D1
D1 --> D2 --> D3 --> E1
E1 --> E2 --> E3 --> E4
style A1 fill:#d4edda
style E4 fill:#cce5ff
(2) قائمة المهارات
| المهارة | الدرس المقابل | مستوى الإتقان |
|---|---|---|
| توجيه نظام ملفات App Router | #03–#06 | إتقان |
| عقلية Server Components | #07 | إتقان |
| استرجاع البيانات والتخزين المؤقت | #08–#11 | إتقان |
| Server Actions CRUD | #12-#13، #29 | إتقان |
| المصادقة والتفويض | #15، #27 | متمكن |
| Prisma ORM وقاعدة البيانات | #16، #27 | متمكن |
| الاختبار (Vitest + Playwright) | #21-#22 | متمكن |
| خط أنابيب CI/CD | #23، #30 | متمكن |
| حل النشر المزدوج Vercel + Docker | #24، #30 | متمكن |
| مراقبة الأداء وتحسينه | #25، #30 | متمكن |
| الأمان والترحيل | #26 | تعلم |
| PPR + مكونات التخزين المؤقت | #10-#11 | إتقان (حصري) |
(3) مجالات للدراسة المستقبلية
| الموضوع | محتوى التعلم | المصادر الموصى بها |
|---|---|---|
| تكامل الذكاء الاصطناعي | Vercel AI SDK + RAG + Streaming | vercel/ai (10k⭐) |
| الواجهات الأمامية المصغرة | Module Federation + Turborepo | Nx / Turborepo الرسمي |
| GraphQL | Apollo + Next.js + Codegen | Apollo Client Docs |
| تطبيقات الوقت الفعلي | WebSocket + Socket.io + Liveblocks | Liveblocks Next.js Integration |
| الحوسبة الطرفية | Edge Functions + Durable Objects | Cloudflare Workers |
| هندسة المنصات | Backstage + بوابة المطور الداخلية | Spotify Backstage |
❓ أسئلة شائعة
node_modules.@latest/next فقط الحد الأدنى من مجموعة الملفات المطلوبة لوقت التشغيل (ملف server.js والأدلة الفرعية لـ .next)، مستبعدا الحزم غير الضرورية من node_modules. عند استخدامه مع بناء Docker متعدد المراحل، تحتوي الصورة النهائية على وقت تشغيل Next.js فقط، مما يقلل حجمها وسطح الهجوم بشكل كبير.📖 ملخص
- نشر Vercel بدون إعداد:
vercel --prodللنشر الفوري بأمر واحد؛ يدعم environment variables والنطاقات و PostgreSQL - ثلاث حاويات Docker للنشر الذاتي: Nginx (وكيل عكسي + SSL) + تطبيق Node.js (مراقب PM2) + PostgreSQL (استمرارية)
- بناء Dockerfile متعدد المراحل يضغط صورة 1.2 جيجابايت إلى 358 ميجابايت، تحتوي على ملفات وقت التشغيل فقط
- GitHub Actions CI/CD: الجودة → البناء → النشر → lighthouse — خط أنابيب آلي من أربع مراحل
- تعيين عتبة درجة 90+ في Lighthouse CI للتحقق التلقائي من pull requests ومنع تدهور الأداء
- PostHog يتتبع أحداث المستخدم (مشاهدات الصفحة، نقرات الأزرار، مسارات التحويل)، بينما Sentry يلتقط أخطاء وقت التشغيل
@vercel/speed-insights+@vercel/analytics— وصول بدون إعداد لمراقبة المستخدم الحقيقي- Bundle Analyzer يعرض حجم الحزمة بصريا؛ الهدف < 300 كيلوبايت JS أولي
- TaskFlow هو اختبار شامل لقدرات Next.js 16 الكاملة: من التوجيه، RSC، PPR، و Server Actions إلى Prisma، Auth.js، و CI/CD
📝 تمارين
-
تمرين أساسي (⭐): انشر TaskFlow على Vercel (حساب مجاني)، قم بإعداد نطاق مخصص (اختياري)، وتحقق من أن
/api/healthيعيد رمز الحالة 200. قم بإعداد environment variableNEXT_PUBLIC_POSTHOG_KEYوتأكد من أن PostHog يستقبل حدث مشاهدة الصفحة. -
تمرين متقدم (⭐⭐): اختبر حل Docker للنشر الذاتي محليا — قم ببناء صورة Docker، وشغل
docker-compose(App + Nginx + PostgreSQL)، وقم بإعداد شهادة SSL موقعة ذاتيا، وشغل ترحيل قاعدة البيانات، وتحقق من الوصول عبر HTTPS. قم بإيداعdocker-compose.ymlوnginx.confوDockerfileفي مستودع المشروع. -
تحدي (⭐⭐⭐): نفذ مراقبة كاملة الوظائف لـ TaskFlow: عرف 5 أحداث رئيسية في PostHog (task_created / task_completed / user_signup / file_uploaded / project_created) وأضف سمات (المدة، المتصفح، الموقع الجغرافي)؛ قم بإعداد قواعد التنبيه في Sentry (إرسال إشعارات Slack وتنبيهات PagerDuty عندما يتجاوز معدل الخطأ 5%)؛ أضف خطوات اختبار Playwright E2E إلى GitHub Actions (نشر → E2E → Lighthouse بالتسلسل)؛ أخيرا، قدم ملف README.md يحتوي على: رسم تخطيطي لهندسة النشر، لقطات شاشة للوحة مراقبة المراقبة، تقرير Lighthouse، وشارة حالة CI/CD.