
اگر بخواهیم واقعبین باشیم، خیلی وقتها وقتی صحبت از CI/CD میشود، ذهن ما به سرعت به سمت DevOps یا ابزارهای پیچیده میرود. اما برای یک فرانتاند سنیور، مفهوم اصلی CI/CD چندان پیچیده نیست؛ مهم این است که بدانیم چرا و چگونه میتواند روند توسعه و تحویل پروژه را ساده کند.
CI (Continuous Integration) یعنی یکپارچهسازی مداوم. هر بار که تغییراتی در کد ایجاد میکنیم، این تغییرات باید با نسخهی اصلی پروژه ترکیب شوند و مطمئن شویم که چیزی شکسته نشده است. برای فرانتاند، این معمولاً شامل:
کامپایل کردن کد (مثلاً TypeScript → JavaScript)
اجرای تستها (واحد، یکپارچه و بعضاً end-to-end)
بررسی linting و استانداردهای کدنویسی
CD (Continuous Delivery / Deployment) یعنی تحویل یا انتشار مداوم. بعد از CI، هدف این است که نسخهی قابل استفادهای از اپلیکیشن آماده باشد. دو نوع اصلی داریم:
Continuous Delivery: کد آمادهی انتشار است، اما انتشار نهایی نیاز به تایید دارد.
Continuous Deployment: کد بدون دخالت دستی، مستقیماً به محیط تولید منتشر میشود.
شاید برای یک تیم کوچک، CI/CD به نظر اضافه بار بیاید. اما با کمی تجربه میفهمیم که وقتی پروژه بزرگتر میشود و چندین نفر همزمان روی بخشهای مختلف کار میکنند، CI/CD باعث میشود:
خطاها سریعتر کشف شوند.
استقرار به محیطهای staging و production امنتر و قابل پیشبینیتر شود.
زمان صرف شده برای رفع باگهای ناشی از ادغام کد کاهش یابد.
فرایند انتشار بدون استرس و قابل تکرار باشد.
برای یک پروژهی فرانتاند، pipeline معمولاً شامل مراحل زیر است:
Pull & Install Dependencies
هر تغییر جدید با git pull دریافت میشود و dependencies با npm install یا yarn install بهروز میشوند.
Linting & Code Quality
ابزارهایی مثل ESLint و Prettier بررسی میکنند که کد مطابق استاندارد تیم باشد. این مرحله معمولاً خطاهای رایج را قبل از تست و بیلد میگیرد.
Unit & Integration Tests
تستهای واحد (Unit) و یکپارچه (Integration) اجرا میشوند. برای React/Vue/Svelte، معمولاً از Jest یا Testing Library استفاده میکنیم.
Build
کد Transpile و Bundle میشود (مثلاً با Vite، Webpack یا Parcel).
هدف این مرحله این است که نسخهی نهایی آمادهی اجرا باشد و مطمئن شویم که هیچ error یا warning حیاتی در زمان build وجود ندارد.
E2E Tests (اختیاری اما توصیهشده)
اگر پروژه پیچیده است، تستهای End-to-End با Cypress یا Playwright اجرا میشوند تا رفتار اپلیکیشن در مرورگر واقعی شبیهسازی شود.
Deploy
بسته به استراتژی تیم:
Staging: برای آزمایش تیم داخلی
Production: نسخهی نهایی که کاربران دریافت میکنند
ابزارهایی مثل Netlify, Vercel, AWS Amplify یا GitHub Actions برای انتشار خودکار مناسب هستند.
فرض کنیم میخواهیم وقتی یک Pull Request ساخته شد یا کدی به main branch فرستاده شد، خودکار تست، بیلد و deploy انجام شود. اینجا یک pipeline ساده با GitHub Actions طراحی میکنیم.
در پروژه، یک فولدر ایجاد میکنیم:
.github/workflows/ci-cd.yml
محتوا فایل :
name: Frontend CI/CD on: push: branches: - main pull_request: branches: - main jobs: build-and-test: runs-on: ubuntu-latest steps: # 1. کلون کردن کد - name: Checkout code uses: actions/checkout@v3 # 2. نصب Node.js - name: Setup Node uses: actions/setup-node@v3 with: node-version: 20 # 3. نصب dependencies - name: Install dependencies run: npm ci # 4. بررسی lint - name: Lint run: npm run lint # 5. اجرای تستها - name: Run tests run: npm test -- --watchAll=false # 6. بیلد پروژه - name: Build run: npm run build deploy: needs: build-and-test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: node-version: 20 - name: Install dependencies run: npm ci - name: Build run: npm run build # 7. Deploy به Vercel (مثال) - name: Deploy to Vercel uses: amondnet/vercel-action@v20 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-args: '--prod' working-directory: .
کد پروژه از GitHub کلون میشود تا CI/CD روی آخرین نسخه اجرا شود.
Node.js نصب میشود تا environment آماده باشد. مهم است که نسخه Node هماهنگ با پروژه باشد.
npm ci dependencies را دقیقاً مطابق package-lock.json نصب میکند تا نسخهها ثابت و قابل پیشبینی باشند.
کد توسط ESLint بررسی میشود. این مرحله کمک میکند اشتباهات رایج و ناسازگاری با استاندارد تیم سریع پیدا شود.
تستهای واحد و integration اجرا میشوند. اگر هر تستی fail شود، pipeline متوقف میشود و کد به main branch merge نمیشود.
کد Transpile و Bundle میشود (مثلاً با Vite). این مرحله نشان میدهد که اپلیکیشن آماده deploy است.
نسخهی build شده به Vercel (یا Netlify، S3، هر سرویس دلخواه) منتشر میشود. با if: github.ref == 'refs/heads/main' مطمئن میشویم فقط تغییرات main deploy شوند.
تقسیم jobs
تست و بیلد در یک job
deploy در job جداگانه که فقط بعد از موفقیت job قبلی اجرا میشود (needs: build-and-test)
Secrets و Environment Variables
Tokenهای deploy (مثل Vercel یا Netlify) را هرگز مستقیم داخل repo نریزیم. از GitHub Secrets استفاده میکنیم.
Pull Request Checks
با این pipeline، هر PR قبل از merge تست و lint میشود. این یعنی main همیشه سالم و deployable باقی میماند.
Rollback آسان
سرویسهایی مثل Vercel یا Netlify نسخههای قبلی را نگه میدارند. اگر deploy جدید مشکل داشت، میتوان سریع rollback کرد.
Visibility
GitHub Actions تمام logs را ذخیره میکند. میتوانیم جزئیات خطاها را بررسی کنیم بدون اینکه دسترسی مستقیم به سرور داشته باشیم.
CI/CD برای فرانتاند نه یک ابزار پیچیده، بلکه یک چارچوب برای اطمینان از کیفیت و سرعت توسعه است. هدف این است که هر تغییر، درست منتشر شود
امیدوارم مفید باشه :)