تحسين مقياس LCP: دليل عملي لتحليل وإصلاح المراحل الأربع

دليل عملي لتحسين مقياس LCP من خلال تحليل وإصلاح مراحله الأربع: TTFB، تأخير اكتشاف المورد، مدة التحميل، وتأخير العرض. يتضمن أمثلة كود تطبيقية وتقنيات حديثة مثل Speculation Rules API والتحميل المسبق والصور المتجاوبة بصيغة AVIF.

ما هو مقياس LCP ولماذا يُعتبر الأهم في 2026؟

لنبدأ من الأساس. مقياس Largest Contentful Paint (LCP) — أو "أكبر رسم محتوى" — يقيس الزمن الذي يستغرقه أكبر عنصر مرئي في منطقة العرض حتى يظهر بالكامل على الشاشة. هذا العنصر قد يكون صورة رئيسية (hero image)، فيديو، أو حتى كتلة نصية كبيرة. ببساطة، هو اللحظة التي يقول فيها المستخدم: "أوكي، الصفحة تحمّلت."

الآن، لماذا أصبح هذا المقياس بالذات بالغ الأهمية؟

في 2026، زادت Google من وزن إشارات تجربة الصفحة في خوارزميات الترتيب بشكل ملحوظ. وبما أن LCP هو المؤشر الأساسي لسرعة التحميل المُدركة من وجهة نظر المستخدم، فإن أي تأخر فيه يعني خسارة مباشرة — سواء في الترتيب أو في معدلات التحويل. والأرقام صريحة: وفقًا لتقرير Chrome User Experience Report، أكثر من 40% من المواقع لا تزال تفشل في تحقيق عتبة LCP الجيدة. وعلى الأجهزة المحمولة؟ النسبة أسوأ بكثير.

عتبات أداء LCP

  • جيد: 2.5 ثانية أو أقل — تجربة سلسة والمستخدم لا يلاحظ أي انتظار
  • يحتاج تحسين: بين 2.5 و4.0 ثوانٍ — تأخر يبدأ المستخدم بالشعور به (وربما يضغط زر الرجوع)
  • ضعيف: أكثر من 4.0 ثوانٍ — تجربة سيئة تؤدي لمغادرة المستخدم ببساطة

والمعيار الذي تعتمده Google واضح: يجب أن يحقق 75% على الأقل من زيارات صفحتك نتيجة "جيد" حتى تجتاز تقييم Core Web Vitals. ليس المتوسط — بل النسبة المئوية 75.

المفتاح الحقيقي: المراحل الأربع التي يتكون منها LCP

هنا النقطة التي تفصل بين من يحاول تحسين LCP بالتجربة والخطأ، ومن يعرف بالضبط أين يضع إصبعه على المشكلة.

الزمن النهائي لمقياس LCP ليس رقمًا واحدًا غامضًا — بل هو مجموع أربع مراحل فرعية متتالية. صراحةً، فهم هذا التقسيم غيّر طريقة تعاملي مع مشاكل الأداء بالكامل.

المرحلة 1: زمن الاستجابة الأولى (TTFB)

هذه المرحلة تغطي كل ما يحدث من لحظة طلب الصفحة حتى وصول أول بايت من HTML إلى المتصفح. نتحدث هنا عن: استعلام DNS، اتصال TCP/TLS، ومعالجة الطلب على الخادم.

هي الأساس الذي يُبنى عليه كل شيء. وإذا كانت بطيئة، فلن ينفع أي تحسين بعدها مهما كان ذكيًا.

الرقم الصادم؟ المواقع التي تعاني من LCP سيء تقضي في المتوسط 2.27 ثانية على TTFB وحدها. فكّر في الأمر — هذا يكاد يستهلك ميزانية الـ 2.5 ثانية كاملة قبل أن يبدأ المتصفح بفعل أي شيء آخر!

المرحلة 2: تأخير اكتشاف المورد (Resource Load Delay)

هذه — بصراحة — هي المرحلة الأكثر إغفالًا والأكثر تأثيرًا في آن واحد. إنها الفترة بين وصول أول بايت من HTML وبين أن يبدأ المتصفح فعليًا في تحميل مورد LCP (الصورة الرئيسية مثلًا). لاحظ: ليست مدة التحميل نفسها، بل زمن الاكتشاف — أي متى "يعرف" المتصفح أنه بحاجة لهذا المورد.

والبيانات هنا مذهلة فعلًا. الموقع المتوسط ذو LCP الضعيف يقضي 1.3 ثانية في انتظار بدء تحميل صورة LCP — أربعة أضعاف الزمن الفعلي لتحميلها. أكثر من نصف ميزانية LCP تضيع في مجرد "الانتظار".

المرحلة 3: مدة تحميل المورد (Resource Load Duration)

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

المرحلة 4: تأخير عرض العنصر (Element Render Delay)

المرحلة الأخيرة، والمفاجئة أحيانًا. هي الزمن من انتهاء تحميل مورد LCP حتى رسمه فعليًا على الشاشة. هذه ليست مشكلة شبكة — بل مشكلة الخيط الرئيسي (Main Thread). المتصفح لديه الصورة جاهزة، لكنه مشغول جدًا بتنفيذ JavaScript أو تحليل CSS ليرسمها. محبط، أليس كذلك؟

كيف تشخّص أي مرحلة تسبب المشكلة؟

قبل أن تقفز إلى الإصلاح (وهو خطأ يرتكبه الكثيرون)، تحتاج أن تعرف بالضبط أين يكمن الاختناق. لا تضيّع وقتك في تحسين مرحلة ليست هي المشكلة.

استخدام Performance API في المتصفح

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

// قياس المراحل الأربع لـ LCP
new PerformanceObserver((entryList) => {
  const entries = entryList.getEntries();
  const lastEntry = entries[entries.length - 1];

  const navEntry = performance.getEntriesByType('navigation')[0];
  const resEntry = performance.getEntriesByName(lastEntry.url)[0];

  // المرحلة 1: TTFB
  const ttfb = navEntry.responseStart;

  // المرحلة 2: تأخير تحميل المورد
  const resourceLoadDelay = resEntry
    ? resEntry.requestStart - ttfb
    : 0;

  // المرحلة 3: مدة تحميل المورد
  const resourceLoadDuration = resEntry
    ? resEntry.responseEnd - resEntry.requestStart
    : 0;

  // المرحلة 4: تأخير العرض
  const elementRenderDelay = resEntry
    ? lastEntry.renderTime - resEntry.responseEnd
    : lastEntry.renderTime - ttfb;

  console.log('LCP Sub-Parts:', {
    ttfb: Math.round(ttfb),
    resourceLoadDelay: Math.round(resourceLoadDelay),
    resourceLoadDuration: Math.round(resourceLoadDuration),
    elementRenderDelay: Math.round(elementRenderDelay),
    totalLCP: Math.round(lastEntry.renderTime)
  });
}).observe({ type: 'largest-contentful-paint', buffered: true });

استخدام Chrome DevTools

الطريقة الأسرع: افتح لوحة Performance في Chrome DevTools، سجّل تحميل الصفحة، وابحث عن علامة LCP في الجدول الزمني. انقر على عنصر LCP لترى تفاصيل التوقيت لكل مرحلة. وإذا كنت تفضل شيئًا أبسط، PageSpeed Insights يعرض عنصر LCP مباشرة في قسم التشخيصات مع توصيات واضحة.

تحسين المرحلة 1: تسريع TTFB

TTFB هو الأساس — وهذه ليست مبالغة. كل مللي ثانية تُضاف هنا تنتقل حرفيًا إلى LCP النهائي بنسبة 1:1. فلنبدأ بأقوى التقنيات.

استخدام CDN مع التخزين المؤقت على الحافة

شبكة توصيل المحتوى (CDN) تقرّب المحتوى جغرافيًا من المستخدم، وهذا أمر أساسي. لكن الاستفادة الحقيقية تأتي من التخزين المؤقت على الحافة (Edge Caching) — بدلًا من العودة لخادم الأصل في كل طلب:

# إعداد Cache-Control لتخزين HTML على CDN
# مع إعادة التحقق في الخلفية
Cache-Control: public, max-age=60, stale-while-revalidate=3600

# للأصول الثابتة (CSS, JS, صور) — تخزين طويل
Cache-Control: public, max-age=31536000, immutable

لاحظ استخدام stale-while-revalidate — هذه الخاصية ذكية جدًا لأنها تقدّم النسخة المخزنة فورًا بينما تحدّث النسخة في الخلفية.

تفعيل HTTP/3 و Early Hints

بروتوكول HTTP/3 يستخدم QUIC بدلًا من TCP، وهذا يلغي زمن مصافحة TCP تمامًا ويقلل TTFB بشكل واضح — خاصة على الشبكات غير المستقرة (وهي أغلب شبكات الموبايل). أما HTTP 103 Early Hints فهي تقنية رائعة تتيح للخادم إرسال تلميحات للمتصفح قبل حتى اكتمال معالجة الاستجابة:

# مثال على Early Hints في Nginx
location / {
    # إرسال تلميحات مبكرة لتحميل الموارد الحرجة
    add_header Link "</css/critical.css>; rel=preload; as=style" early;
    add_header Link "</images/hero.avif>; rel=preload; as=image" early;

    proxy_pass http://backend;
}

التخزين المؤقت للصفحات الكاملة

إذا كان محتوى صفحتك لا يتغير مع كل طلب (وهذا حال معظم الصفحات بصراحة)، فإن Full Page Caching باستخدام Varnish أو Redis يمكن أن يخفض TTFB من ثوانٍ إلى أجزاء من المللي ثانية — فرق هائل:

# إعداد Varnish لتخزين الصفحات
sub vcl_backend_response {
    # تخزين الصفحات لمدة 5 دقائق
    if (bereq.url ~ "\.(html|htm)$") {
        set beresp.ttl = 300s;
        set beresp.grace = 1h;
    }
}

تحسين المرحلة 2: تقليل تأخير اكتشاف المورد

هذه المرحلة هي حيث تضيع معظم الميزانية الزمنية دون أن يلاحظها أحد. وإليك القاعدة الذهبية التي يجب أن تحفظها: يجب أن يكون مورد LCP قابلًا للاكتشاف مباشرة من مستند HTML.

تجنّب صور الخلفية CSS لعنصر LCP

ماسح التحميل المسبق (preload scanner) في المتصفح يستطيع اكتشاف عناصر <img> في HTML مباشرة أثناء تحليله، لكنه لا يستطيع اكتشاف صور CSS background لأنها تحتاج تحميل وتحليل CSS أولًا. إذا كانت صورتك الرئيسية هي عنصر LCP، الحل بسيط:

<!-- سيء: المتصفح لن يكتشف الصورة حتى يحلل CSS -->
<div class="hero" style="background-image: url('/images/hero.avif')"></div>

<!-- جيد: المتصفح يكتشف الصورة فورًا من HTML -->
<img src="/images/hero.avif"
     alt="وصف الصورة الرئيسية"
     width="1200"
     height="600"
     fetchpriority="high">

استخدام preload لمورد LCP

إذا لم يكن بإمكانك وضع مورد LCP مباشرة في HTML (لسبب تقني أو تصميمي)، استخدم <link rel="preload"> كحل بديل فعّال:

<head>
  <!-- التحميل المسبق لصورة LCP -->
  <link rel="preload"
        href="/images/hero.avif"
        as="image"
        type="image/avif"
        fetchpriority="high">

  <!-- مع دعم الصور المتجاوبة -->
  <link rel="preload"
        as="image"
        href="/images/hero-800.avif"
        imagesrcset="/images/hero-400.avif 400w,
                     /images/hero-800.avif 800w,
                     /images/hero-1200.avif 1200w"
        imagesizes="100vw"
        fetchpriority="high">
</head>

لا تستخدم lazy loading على عنصر LCP — أبدًا

هذا خطأ شائع أراه كثيرًا، وهو مؤلم. إضافة loading="lazy" على الصورة التي هي عنصر LCP يؤخر تحميلها حتى يقترب المستخدم من رؤيتها — وهو عكس ما تريده تمامًا. أنت تقول للمتصفح "لا تهتم بهذه الصورة الآن" بينما هي أهم عنصر في الصفحة!

<!-- خطأ فادح: lazy loading على صورة LCP -->
<img src="/images/hero.webp" loading="lazy" alt="...">

<!-- الصحيح: eager loading مع أولوية عالية -->
<img src="/images/hero.webp"
     loading="eager"
     fetchpriority="high"
     alt="...">

تحسين المرحلة 3: تقليل حجم مورد LCP

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

استخدام صيغ الصور الحديثة: AVIF أولًا

في 2026، AVIF هو الخيار الأمثل لصور LCP بلا منازع. يوفر ضغطًا أفضل من WebP بنسبة تصل إلى 50% إضافية مع جودة بصرية ممتازة. استخدم عنصر <picture> مع ترتيب الأولويات من الأفضل للأقل:

<picture>
  <!-- AVIF أولًا: أفضل ضغط -->
  <source srcset="/images/hero-400.avif 400w,
                  /images/hero-800.avif 800w,
                  /images/hero-1200.avif 1200w"
          sizes="100vw"
          type="image/avif">

  <!-- WebP كبديل -->
  <source srcset="/images/hero-400.webp 400w,
                  /images/hero-800.webp 800w,
                  /images/hero-1200.webp 1200w"
          sizes="100vw"
          type="image/webp">

  <!-- JPEG كشبكة أمان أخيرة -->
  <img src="/images/hero-800.jpg"
       srcset="/images/hero-400.jpg 400w,
              /images/hero-800.jpg 800w,
              /images/hero-1200.jpg 1200w"
       sizes="100vw"
       alt="وصف الصورة"
       width="1200"
       height="600"
       loading="eager"
       fetchpriority="high"
       decoding="async">
</picture>

ضغط الصور تلقائيًا في خط البناء

نصيحة مهمة: لا تعتمد على الضغط اليدوي. ستنسى حتمًا. أدمج الضغط في عملية البناء (build pipeline) ليعمل تلقائيًا:

// vite.config.js — مثال مع vite-plugin-imagemin
import imagemin from 'vite-plugin-imagemin';

export default {
  plugins: [
    imagemin({
      avif: {
        quality: 65,  // توازن ممتاز بين الجودة والحجم
        speed: 5
      },
      webp: {
        quality: 75
      },
      mozjpeg: {
        quality: 80  // بديل JPEG محسّن
      }
    })
  ]
};

تحسين المرحلة 4: تقليل تأخير العرض

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

إزالة CSS الحاجب للعرض

بشكل افتراضي، ملفات CSS تحجب العرض — المتصفح لن يرسم أي شيء على الإطلاق حتى يحمّل ويحلل جميع ملفات CSS الموجودة في <head>. الحل العملي: ادمج CSS الحرج (critical CSS) مباشرة في HTML كأنماط مضمّنة، وأجّل تحميل الباقي:

<head>
  <!-- CSS حرج مدمج مباشرة -->
  <style>
    /* فقط الأنماط المطلوبة لأول عرض */
    .hero { position: relative; width: 100%; }
    .hero img { width: 100%; height: auto; display: block; }
    /* ... */
  </style>

  <!-- تحميل CSS غير الحرج بشكل غير حاجب -->
  <link rel="preload" href="/css/main.css" as="style"
        onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/css/main.css"></noscript>
</head>

تأجيل JavaScript غير الحرج

أي ملف JavaScript في <head> بدون defer أو async يحجب تحليل HTML بالكامل — وبالتالي يؤخر عرض عنصر LCP. وهذه من أسهل المشاكل حلًا:

<!-- سيء: يحجب التحليل والعرض -->
<script src="/js/analytics.js"></script>

<!-- جيد: يُنفذ بعد تحليل HTML -->
<script src="/js/analytics.js" defer></script>

<!-- للسكربتات غير الضرورية: تحميل بعد التفاعل -->
<script>
  // تأجيل السكربتات غير الحرجة حتى يتفاعل المستخدم
  const loadDeferredScripts = () => {
    const scripts = ['chat-widget.js', 'social-share.js'];
    scripts.forEach(src => {
      const s = document.createElement('script');
      s.src = src;
      document.body.appendChild(s);
    });
  };

  if ('requestIdleCallback' in window) {
    requestIdleCallback(loadDeferredScripts);
  } else {
    setTimeout(loadDeferredScripts, 3000);
  }
</script>

تقنية متقدمة: Speculation Rules API لتنقل فوري

هذه التقنية — بصراحة — من أكثر ما أثار حماسي مؤخرًا. في 2026، أصبحت Speculation Rules API مدعومة على نطاق واسع في المتصفحات المبنية على Chromium. الفكرة بسيطة لكنها قوية: تخبر المتصفح بالصفحات التي يُحتمل أن يزورها المستخدم، فيحمّلها أو حتى يعرضها مسبقًا (prerender) — مما يجعل LCP للتنقل التالي يساوي صفرًا تقريبًا.

نعم، صفر. لأن كل شيء حدث فعلًا في الخلفية.

<script type="speculationrules">
{
  "prerender": [
    {
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/logout" } },
          { "not": { "href_matches": "/api/*" } }
        ]
      },
      "eagerness": "moderate"
    }
  ],
  "prefetch": [
    {
      "where": { "selector_matches": ".product-card a" },
      "eagerness": "eager"
    }
  ]
}
</script>

مع العرض المسبق، جميع المراحل الأربع (TTFB، تأخير الاكتشاف، مدة التحميل، تأخير العرض) تحدث في الخلفية قبل أن ينقر المستخدم. النتيجة؟ تنقل فوري يشعر وكأنه تطبيق محلي.

قائمة مراجعة سريعة: أولويات التحسين

بناءً على بيانات الاستخدام الحقيقي وتجربتي العملية، إليك ترتيب الأولويات من الأكثر تأثيرًا:

  1. قلّل TTFB أولًا — استخدم CDN وتخزين مؤقت وخادم سريع. ببساطة، لا تحسين يعوّض خادمًا بطيئًا.
  2. اجعل مورد LCP قابلًا للاكتشاف في HTML — استخدم <img> بدلًا من CSS background، وأضف preload عند الحاجة.
  3. لا تضع lazy loading على عنصر LCP — استخدم loading="eager" مع fetchpriority="high".
  4. استخدم صيغ AVIF/WebP — مع صور متجاوبة عبر srcset وعنصر picture.
  5. أزل CSS و JS الحاجبة للعرض — ادمج CSS الحرج مباشرة وأجّل تحميل الباقي.
  6. فعّل Speculation Rules API — للتنقل الفوري بين الصفحات (تحسين تدريجي لا يضر المتصفحات غير الداعمة).

الأسئلة الشائعة

ما الفرق بين LCP و FCP؟

مقياس First Contentful Paint (FCP) يقيس زمن ظهور أول محتوى مرئي على الشاشة — وقد يكون مجرد نص صغير أو مؤشر تحميل. أما LCP فيقيس زمن ظهور أكبر عنصر محتوى، وهو ما يهم المستخدم فعلًا. يمكن أن يكون FCP سريعًا جدًا بينما LCP بطيء — مثلًا إذا ظهر النص فورًا لكن الصورة الرئيسية تأخرت.

هل يؤثر حجم شجرة DOM على LCP؟

نعم، لكن بشكل غير مباشر. شجرة DOM الكبيرة تزيد من زمن المرحلة الرابعة (تأخير العرض) لأن المتصفح يحتاج وقتًا أطول لحساب التخطيط والرسم. توصي Google بأن تكون شجرة DOM أقل من 1,500 عقدة وبعمق أقل من 32 مستوى.

هل Lazy Loading يضر دائمًا بمقياس LCP؟

ليس دائمًا — فقط إذا استخدمته على عنصر LCP نفسه. خاصية loading="lazy" تؤخر تحميل الصورة حتى تقترب من منطقة العرض، وهذا كارثي لعنصر LCP الذي يجب أن يُحمّل فورًا. القاعدة: استخدم lazy loading على الصور أسفل الطية (below the fold) فقط، وضع loading="eager" مع fetchpriority="high" على صورة LCP.

كيف أحدد عنصر LCP في صفحتي؟

أسهل طريقة: افتح PageSpeed Insights وأدخل رابط صفحتك — في قسم "التشخيصات" ستجد "Largest Contentful Paint element" مع تحديد العنصر بالضبط. بديل آخر: لوحة Performance في Chrome DevTools أو إضافة Web Vitals لمتصفح Chrome.

ما هي Speculation Rules API وهل تعمل في جميع المتصفحات؟

هي واجهة برمجية تتيح لك إخبار المتصفح بالصفحات المحتمل زيارتها ليحمّلها أو يعرضها مسبقًا. في 2026، هي مدعومة بالكامل في المتصفحات المبنية على Chromium (مثل Chrome وEdge وOpera). Firefox وSafari لا يزالان في مراحل مختلفة من الدعم، لكن لا تقلق — هي تعمل كتحسين تدريجي ولا تؤثر سلبًا على المتصفحات غير الداعمة.

عن الكاتب Editorial Team

Our team of expert writers and editors.