لو موقعك بياخد 4 ثواني علشان يظهر العنصر الرئيسي قدام الزائر، Google بيعتبر ده تجربة سيئة وبيخفّض ترتيبك في البحث. اللي قدامك هنا 4 خطوات مثبتة بأرقام لتنزيل الـ LCP لتحت 1.8 ثانية، من غير ما تغيّر الـ framework أو تعيد كتابة الموقع.
تحسين LCP: الخطوات اللي بتشتغل فعلاً
المشكلة باختصار
الـ Largest Contentful Paint هو الزمن اللي بياخده أكبر عنصر مرئي في الـ viewport علشان يتعرض. غالبًا بيكون صورة hero، أو heading كبير، أو فيديو. Google بيعتبر LCP أحد الـ Core Web Vitals الثلاثة، وبيستخدمه عامل ترتيب فعلي في نتائج البحث منذ 2021.
الحد المقبول من Google: أقل من 2.5 ثانية لـ 75% من زيارات الموقع. أكتر من 4 ثواني = "ضعيف" رسميًا، وده اللي بيخلّي الزائر يقفل التاب قبل ما يخلّص قراءة العنوان.
إيه هو الـ LCP بالظبط — مثال للمبتدئين
تخيّل إن صفحتك ظهرت قدام الزائر، لكن المساحة الرئيسية في النص لسه فاضية. الزائر شايف الـ navbar، شايف الـ background، لكن صورة المنتج الكبيرة في النص لسه بتحمّل. اللحظة اللي الصورة الكبيرة دي تظهر فيها = ده الـ LCP بتاعك.
المتصفح بيقيس ده بالمللي ثانية من لحظة بداية تحميل الصفحة. لو طالك 4200ms = LCP سيء. لو طالك 1800ms = LCP ممتاز.
بشكل علمي ودقيق: الـ LCP هو وقت render أكبر عنصر من نوع img أو video أو block-level text داخل الـ initial viewport، بيتحسب من lifecycle event بإسم largest-contentful-paint في الـ PerformanceObserver API.
الخطوة 1: قِس قبل ما تعدّل
أكبر غلطة بيعملها المطورين هي إنهم يبدأوا يعدّلوا قبل ما يقيسوا. بدون رقم بداية، مش هتعرف لو التعديل نفع ولا لأ. استخدم اتنين أدوات بس:
- PageSpeed Insights — بيديك LCP حقيقي من بيانات Chrome User Experience Report، يعني من زوار حقيقيين مش من جهازك.
- Lighthouse CLI — بيشتغل local وبيديك تفاصيل العنصر اللي بيسبّب الـ LCP.
# تثبيت Lighthouse CLI
npm install -g lighthouse
# تشغيل audit مع تركيز على LCP
lighthouse https://yoursite.com \
--only-categories=performance \
--output=html \
--output-path=./report.html \
--throttling-method=simulate
# هيظهرلك في الـ report:
# Largest Contentful Paint: 4.2 s
# LCP element:
لو الـ Lighthouse اداك LCP عنصره صورة، عرفت إنك محتاج تركّز على تحسين الصور. لو العنصر heading نصي، هتركّز على font loading وserver response time. الفرق ده بيوفّر عليك ساعات شغل في الاتجاه الغلط.
الخطوة 2: حسّن العنصر الرئيسي للـ LCP
لو الـ LCP صورة (الحالة الأشيع، حوالي 70% من المواقع حسب Web Almanac 2023)، فيه 3 إجراءات بترتيب الأولوية:
أ. preload للصورة الرئيسية
<link rel="preload"
as="image"
href="/hero.avif"
fetchpriority="high">
الـ fetchpriority="high" بيقول للمتصفح: "اللي قدامك ده مهم، حمّله الأول قبل أي حاجة تانية". لوحدها التعديلة دي بتقلّل LCP بحوالي 600–1000ms في معظم المواقع.
ب. استخدم AVIF أو WebP بدل JPEG
<picture>
<source srcset="/hero.avif" type="image/avif">
<source srcset="/hero.webp" type="image/webp">
<img src="/hero.jpg" alt="..." width="1200" height="600">
</picture>
صورة AVIF بحجم 80KB بتعطي نفس جودة JPEG بحجم 380KB. على شبكة 4G متوسطة (10Mbps)، الفرق ده بيوفر حوالي 240ms من زمن التحميل.
ج. حدّد width و height دائمًا
من غير الأبعاد، المتصفح بيعمل reflow لمّا الصورة تتحمّل، وده بيأخّر الـ LCP بحوالي 100–200ms ويسبّب Cumulative Layout Shift في نفس الوقت.
الخطوة 3: قلّل زمن استجابة السيرفر (TTFB)
الـ Time To First Byte هو الزمن من لحظة طلب الصفحة لحد ما يوصلك أول بايت من السيرفر. كل ms هنا بيتأخّر، الـ LCP بيتأخّر بنفس القدر — مفيش طريقة تعوّضه في الفرونت.
الافتراض هنا: إنت بتشغّل موقع server-rendered (Next.js SSR، Laravel، Django…). لو موقعك static بالكامل (مثل Astro أو Next.js static export)، تجاوز الخطوة دي.
إجراءات بترتيب الـ ROI:
- CDN في القدّام — Cloudflare أو Bunny مجانًا بيقلّلوا TTFB من 800ms في أوروبا/آسيا لـ 80ms.
- Cache على مستوى الـ HTML — لو الصفحة مش شخصية، خزّنها في Redis لمدة 60 ثانية. التكلفة: تعقيد cache invalidation. المكسب: TTFB بينزل من 400ms لـ 20ms.
- Database connection pooling — لو كل request بيفتح connection جديد، إنت بتخسر 20–40ms في الـ handshake.
الخطوة 4: شيل الـ render-blocking resources
الـ CSS و JavaScript اللي في الـ <head> بدون async أو defer بيوقفوا render الصفحة كلها. ده بيأخّر الـ LCP حتى لو الصورة جاهزة.
<!-- غلط: بيوقف render -->
<script src="/analytics.js"></script>
<!-- صح: بيتحمل من غير ما يوقف -->
<script src="/analytics.js" defer></script>
<!-- للـ CSS غير الحرج -->
<link rel="preload"
href="/non-critical.css"
as="style"
onload="this.rel='stylesheet'">
أداة Lighthouse بتقولك بالظبط أنهي resources بتعمل block. شيلهم واحد واحد وقِس.
trade-offs اللي لازم تعرفها
كل تحسين هنا له تكلفة:
- preload للصور — لو preload أكتر من صورة، هتتعارض مع موارد تانية مهمة وممكن تأخّر TTI. القاعدة: preload لصورة LCP وحدة فقط.
- AVIF — بيحتاج encoding أبطأ على السيرفر (3–5x من JPEG)، فا لو بتعمل image transformation on-demand، هتحتاج cache layer.
- HTML caching — بيحل مشاكل الأداء، لكن بيخلق مشاكل cache invalidation. لو عندك محتوى شخصي، الحل ده مش مناسب.
- defer/async للـ JS — بيكسر سكربتات بتعتمد على ترتيب التنفيذ. اختبر بعد كل تعديل.
متى لا تستخدم هذه الطريقة
لو موقعك dashboard داخلي بيستخدمه 5 موظفين بس، ومفيش SEO، تحسين الـ LCP إهدار وقت. ركّز على Time To Interactive بدل كده. كذلك لو موقعك خلف authentication بالكامل ومش بيظهر في Google — ركّز على المقاييس اللي بتأثّر على المستخدم الفعلي زي input latency.
الافتراض اللي المقال ده مبني عليه: عندك موقع عام، بيستهدف SEO، وعدد زواره ≥ 5K شهريًا. أقل من كده، ROI تحسين LCP بيقل لأن Google بيحتاج بيانات كافية في الـ CrUX report.
المصادر
- Largest Contentful Paint (LCP) — web.dev
- Lighthouse: Largest Contentful Paint — Chrome Developers
- Web Almanac 2022 — Performance Chapter
- MDN: rel=preload
- Optimize LCP — web.dev guide
الخطوة التالية
افتح PageSpeed Insights على الصفحة الرئيسية لموقعك دلوقتي، وسجّل رقم الـ LCP الحالي في ملف نصي. بعدين طبّق تعديل واحد بس من الخطوة 2 (preload للصورة الرئيسية) وأعد القياس بعد 24 ساعة (Google محتاج وقت لتحديث بيانات CrUX). لو الفرق أقل من 200ms، ابعتلي الـ Lighthouse report وهنشوف العنصر اللي بيعطّل الـ render.