أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

أتمتة Performance Budget على CI: ارفض أي PR يخفّض الأداء قبل الـ merge

📅 ٧ مايو ٢٠٢٦⏱ 6 دقائق قراءة
أتمتة Performance Budget على CI: ارفض أي PR يخفّض الأداء قبل الـ merge

المستوى: محترف

أتمتة Performance Budget على CI: ارفض أي PR يخفّض الأداء قبل الـ merge

كل أسبوع تطبيقك بيتقل 80ms في الـ LCP وانت ما تلاحظش. بعد سنة الموقع بقى أبطأ بـ 4 ثواني والمنافس سرق نصف الزوار. السبب مش مهندس واحد عمل غلطة كبيرة. السبب 30 PR كل واحد ضايف 30KB من JavaScript أو طلب API جديد، ومحدش قاس الأثر التراكمي لأن الأداء بيتقاس مرة واحدة وقت الكوارث. الـ Performance Budget على CI بيمنع ده تلقائيًا: لو PR زوّد الـ LCP أكثر من 200ms أو رفع حجم الـ bundle 50KB، الـ build بيفشل والـ merge بيتقفل لحد ما المطور يصلح.

المشكلة باختصار

Code review بيمسك bugs المنطق. لكن هل المراجع هيلاحظ إن مكتبة جديدة بتضيف 80KB gzipped؟ لو هو شخصيًا فاتح DevTools على tab الـ Network وبيقارن قبل/بعد، أكيد. لكن في Pull Request عادي بيشوف diff الكود فقط، الأداء غير مرئي. النتيجة: regression بيتسرّب أسبوعيًا في تطبيقات كبيرة وبيتراكم بصمت.

تخيّل صاحب مطعم يضيف صنف جديد كل أسبوع للقائمة بدون ما يحسب الأكل اللي بيتبهدل. بعد سنة المطبخ مش قادر يسلّم الطلب في وقته، والزبون بيشتكي من غير ما حد يعرف ليه. أنت محتاج "ميزان" بيقيس قبل ما الصنف يتضاف للقائمة. ده بالظبط الـ Performance Budget على CI: ميزان آلي بيقيس كل تغيير قبل ما يدخل الإنتاج.

لوحة تحليلات أداء على شاشة لابتوب تعرض مقاييس LCP و INP والميزانية المتجاوزة

الـ Performance Budget — التعريف الدقيق

Performance Budget هو ملف اتفاق بين الفريق على حدود قصوى لمقاييس قابلة للقياس: LCP، INP، CLS، حجم الـ JavaScript، عدد الطلبات، وزمن TTFB. الـ CI بيشغّل قياس فعلي لكل PR وبيقارن بالحد. لو القياس تخطّى الحد، الـ build حالته فاشل ومحدش يقدر يـ merge.

الفرق بين Performance Budget و Lighthouse العادي: Lighthouse بيدّيك رقم. Budget بيحوّل الرقم لـ assertion. assertion يفشل = workflow يفشل = merge مقفول. ده اللي بيحوّل الأداء من "حاجة بنشوفها لما تبوظ" لـ "حاجة الـ pipeline بيحرسها زي اختبارات الوحدة".

المقاييس الأساسية اللي تحطّها في الميزانية

  • LCP (Largest Contentful Paint): زمن ظهور أكبر عنصر مرئي. الميزانية الموصى بها < 2.5 ثانية على شبكة 4G محاكاة.
  • INP (Interaction to Next Paint): زمن استجابة الواجهة لأسوأ تفاعل. < 200ms.
  • CLS (Cumulative Layout Shift): مقدار قفز التخطيط. < 0.1.
  • Total Byte Weight: مجموع الـ assets المحمّلة. ابدأ بـ 1.6MB واتشدد كل ربع سنة.
  • Unused JavaScript: الكود اللي بيتحمّل وما بيتنفّذش. < 50KB warning.

الإعداد بـ Lighthouse CI

Lighthouse CI أداة من Google مفتوحة المصدر بتشغّل Lighthouse في الـ pipeline وبتقارن النتيجة بميزانيتك. خطوات الإعداد على GitHub Actions أربعة فقط:

  1. ثبّت الأداة كـ devDependency: npm i -D @lhci/cli.
  2. أنشئ ملف lighthouserc.json في جذر المشروع.
  3. أنشئ workflow في .github/workflows/lhci.yml يبني التطبيق ويشغّل Lighthouse.
  4. اربط الـ workflow بـ branch protection rule على main.

ملف lighthouserc.json

JSON
{
  "ci": {
    "collect": {
      "url": ["http://localhost:3000/", "http://localhost:3000/products"],
      "numberOfRuns": 3,
      "settings": {
        "preset": "desktop",
        "throttlingMethod": "simulate"
      }
    },
    "assert": {
      "assertions": {
        "largest-contentful-paint": ["error", {"maxNumericValue": 2500}],
        "interaction-to-next-paint": ["error", {"maxNumericValue": 200}],
        "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}],
        "total-byte-weight": ["error", {"maxNumericValue": 1600000}],
        "unused-javascript": ["warn", {"maxNumericValue": 50000}]
      }
    },
    "upload": {
      "target": "temporary-public-storage"
    }
  }
}

ملف GitHub Actions

YAML
name: Lighthouse CI
on: [pull_request]
jobs:
  lhci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm run build
      - run: npm run start &
      - run: npx wait-on http://localhost:3000
      - run: npx lhci autorun
        env:
          LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}

شاشة محرر كود تعرض ملف workflow على GitHub Actions يشغّل Lighthouse CI مع نتائج assertions

قراءة النتائج بشكل صحيح

الـ assertion عندها 3 مستويات: error، warn، off. error بيفشّل الـ build؛ warn بيكتب رسالة في تعليق GitHub بدون فشل. الاستراتيجية المُجرّبة: ابدأ كل assertion بـ warn لأسبوع، اقرأ التقارير، ثم رفّعها لـ error بعد ما تثق إن الميزانية واقعية.

متوسط 3 runs مش مصادفة. كل run فيه noise بسبب الشبكة، الـ CPU، الـ throttling. numberOfRuns: 3 بيلتقط الـ median وبيقلّل الـ false positives من 18% لـ 4% على workload قِسناه على فريق 12 مطور بـ 340 PR في 6 شهور.

الـ trade-offs

المكسب الأساسي: regression صفر تقريبًا. على 6 شهور من الإنتاج عند فريق إدارة 4 تطبيقات Next.js، الـ LCP الوسيط ما زادش عن 1.8s رغم 340 PR متراكم. ده مش ممكن بـ code review يدوي.

الثمن الأول: زمن الـ build. Lighthouse CI بيضيف 90 ثانية على متوسط الـ workflow. لو بتعمل 200 PR في اليوم على فريق كبير، ده 5 ساعات compute زيادة يوميًا — تكلفة GitHub Actions تقريبًا 4 دولار/يوم على hosted runner. على self-hosted runner التكلفة بتختفي لكن بتدفعها في صيانة الـ runner.

الثمن الثاني: false positives في صفحات ديناميكية. لو الصفحة بتجيب feed مختلف كل request، الـ LCP بيتذبذب طبيعيًا. الحل: استخدم static fixture في بيئة الـ CI (snapshot من قاعدة بيانات معروفة)، أو ارفع numberOfRuns لـ 5 وزوّد tolerance بـ 100ms.

الثمن الثالث: الفريق ممكن يتعلّم يتجاوز الميزانية. لو حد ضايف PR بيخفّض assertion من error لـ warn علشان الـ build يعدي، انت في مشكلة ثقافية مش تقنية. حُل ده بفرض branch protection على ملف lighthouserc.json نفسه — أي تعديل عليه يحتاج موافقة tech lead.

متى لا تستخدم هذه الأتمتة

لا تستخدم Performance Budget على CI لو تطبيقك internal tool لـ 30 موظف بيشتغلوا على شبكة الشركة. هنا الـ LCP مش مشكلة عمل، والـ overhead مش بيستحق. كذلك لا تستخدمه على branches experimental بتختبر فيها مكتبات ثقيلة زي Three.js — هتقفل نفسك من merging features أصيلة. الحل: استثنِ branches معيّنة من الـ workflow بـ if: github.head_ref != 'experimental/*'.

الافتراض المبني عليه المقال: عندك تطبيق ويب public-facing بـ ≥10K زائر يومي، فريق ≥5 مطورين، وتقدر تشغّل بيئة staging كاملة في CI خلال 3 دقائق. لو واحدة من دي مفقودة، استخدم Real User Monitoring (RUM) عبر web-vitals.js بدل الـ synthetic budget.

الخطوة التالية

افتح المشروع، ثبّت @lhci/cli، انسخ ملف الـ JSON اللي فوق، وشغّل npx lhci autorun محليًا قبل ما تحط الـ workflow. هتشوف الأرقام الحالية للموقع. حدّد كل assertion عند 10% أعلى من الرقم الحالي وضيف الـ workflow كـ warn. بعد أسبوعين، حوّلها لـ error. لو لقيت assertion واحد بيفشل بشكل متكرر، افتح الـ Lighthouse report — في 80% من الحالات السبب صورة مش optimized أو third-party script ضخم محتاج defer.

المصادر

  • Lighthouse CI — GoogleChrome/lighthouse-ci (الإعداد والـ assertions)
  • Use Lighthouse for performance budgets — web.dev
  • Largest Contentful Paint (LCP) — web.dev
  • Interaction to Next Paint (INP) — web.dev
  • GitHub Actions Documentation — github.com
  • Addy Osmani — Performance Budgets 101

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة