IT
🚀

تحسين Core Web Vitals — كيف خفضت LCP من 3 ثوانٍ إلى 1.2 ثانية

USD/JPY分散は、為替急変局面で一方通貨の過大シェアを防ぎ、月次の再バランスと上限規則で感情的な一括投資を抑える実践設計です。

تحسين Core Web Vitals — كيف خفضت LCP من 3 ثوانٍ إلى 1.2 ثانية

ملخص رئيسي

  • LCP (Largest Contentful Paint) هو مؤشر رئيسي يؤثر بشكل مباشر على ترتيب بحث Google.
  • تم تقليل LCP من 3.0 ثانية إلى 1.2 ثانية من خلال تطبيق ثلاث استراتيجيات: تحسين الصور، استراتيجيات تحميل الخطوط، وتقسيم الشيفرة.
  • تم خفض CLS من 0.28 إلى 0.04 من خلال تحديد أحجام الصور والإعلانات وإزالة تغييرات التخطيط.
  • هذه النتائج مستندة إلى مشروع Next.js في الإنتاج، ويمكن تطبيق نفس المبادئ على مشاريع React وVue.

مقدمة — لماذا Core Web Vitals؟

monitor screengrab seo analytics seo analytics

عندما أصدرت Google تحديث تجربة الصفحة في عام 2021، أصبحت Core Web Vitals أكثر من مجرد مؤشرات UX، بل أصبحت عوامل مؤثرة في ترتيب SEO. منذ ذلك الحين، استمرت Google في زيادة وزن هذه الإشارات، وفي عام 2024، سيتم استبدال INP (التفاعل مع الطلاء التالي) بـ FID بالكامل، مما يجعل معايير التقييم تتطور.

كان مشروع التجارة الإلكترونية الذي أديره يحصل على درجة مروعة تبلغ 38 نقطة على PageSpeed Insights قبل ستة أشهر. كانت LCP 3.0 ثانية، وCLS 0.28، وINP 320 مللي ثانية — جميع المؤشرات كانت في منطقة "تحتاج إلى تحسين". سأوثق كيف غيرت هذه المؤشرات.


كيف نفهم Core Web Vitals الثلاثة بسرعة؟

computer screen bunch data on it

LCP — سرعة "الانطباع الأول" للصفحة

LCP هو الوقت المستغرق لعرض أكبر عنصر محتوى (عادةً صورة البطل أو نص H1) داخل نافذة العرض. وفقًا لـ Google، فإن أقل من 2.5 ثانية يعتبر جيدًا، وأكثر من 4.0 ثوانٍ يعتبر سيئًا.

غالبًا ما تكون صورة البطل هي العنصر المستهدف لـ LCP في مواقع التجارة الإلكترونية. إذا لم يتم تحميل هذه الصورة في الوقت المناسب، فإن جميع التحسينات الأخرى تصبح بلا جدوى.

CLS — هل التخطيط "يقفز"؟

CLS (Cumulative Layout Shift) يقيس مدى حركة العناصر بشكل غير متوقع أثناء تحميل الصفحة. إذا تم إدراج لافتة إعلانات في وقت متأخر، أو تم تحميل صورة بدون تحديد حجمها، فإن النتيجة ترتفع. أقل من 0.1 هو المعيار الجيد.

INP — مدى سرعة استجابة المستخدمين؟

INP يقيس تأخير الاستجابة لجميع التفاعلات مثل النقرات، واللمسات، وإدخال لوحة المفاتيح. استبدل FID في مارس 2024، وأقل من 200 مللي ثانية هو المعيار الجيد. كلما كانت حزم JavaScript أثقل، كلما زادت احتمالية انسداد الخيط الرئيسي، مما يؤدي إلى تدهور INP.


تشخيص المشكلة — النتائج الأولية للقياس

close up computer screen blurry background

تسجيل المؤشرات بدقة قبل التحسين هو نقطة البداية. استخدمت الأدوات التالية بالترتيب:

  1. 1PageSpeed Insights — يقدم بيانات حقلية (بيانات المستخدمين الفعلية) وبيانات مختبرية (Lighthouse) في نفس الوقت.
  2. 2Chrome DevTools > علامة الأداء — تحقق من الجدول الزمني للرسم والعناصر المرشحة لـ LCP.
  3. 3WebPageTest — قياس فعلي بناءً على خادم CDN المحلي، تحقق بصريًا باستخدام شريط الفيلم.
  4. 4Vercel Analytics / Sentry — جمع Core Web Vitals بناءً على جلسات المستخدمين الفعلية.

أظهرت نتائج التشخيص أن الاختناقات كانت في ثلاثة أماكن.

  • صورة البطل — 4.2 ميغابايت JPEG، تم إدراجها مباشرة باستخدام علامة بدون تحسين.
  • خطوط Google — تحميل ثلاثة عائلات خطوط بشكل متزامن باستخدام طريقة @import.
  • حجم الحزمة — الكتلة الرئيسية 1.8 ميغابايت، تحتوي على العديد من المكتبات التي لم يتم تطبيق تقليم الشجرة عليها.

كيف خفضت LCP من 3.0 ثانية إلى 1.2 ثانية باستخدام ثلاث طرق؟

الطريقة 1 — تحسين الصور والتحميل المسبق

كانت هذه الطريقة الأكثر فعالية. غيرت تمامًا طريقة معالجة صورة البطل.

قبل

html
<img src="/banner.jpg" alt="البانر الرئيسي" />

بعد — مكون صورة Next.js + تحويل WebP

jsx
import Image from 'next/image';

<Image
  src="/banner.webp"
  alt="البانر الرئيسي"
  width={1920}
  height={800}
  priority          // يجب أن تكون الصورة المستهدفة لـ LCP ذات أولوية
  quality={80}
  sizes="(max-width: 768px) 100vw, 1920px"
/>

بمجرد إضافة خاصية priority، يقوم Next.js تلقائيًا بإدراج علامة لهذه الصورة. بعد تحويل WebP، انخفض حجم الملف من 4.2 ميغابايت إلى 340 كيلوبايت، مما يمثل انخفاضًا بنسبة 92%.

إذا كنت تستخدم مشروع HTML/React بسيط، يمكنك إضافة علامة التحميل المسبق مباشرة داخل .

html
<link
  rel="preload"
  as="image"
  href="/banner.webp"
  type="image/webp"
/>

بهذه الخطوة وحدها، انخفض LCP من 3.0 ثانية إلى 1.8 ثانية.

الطريقة 2 — تغيير استراتيجية تحميل الخطوط

عند استيراد خطوط Google باستخدام @import، يتوقف المتصفح عن تحليل CSS ويرسل طلب الخط. هذه الفترة الانتظارية تزيد بشكل كبير من LCP.

قبل

html
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap');
</style>

بعد — + display=swap + استضافة ذاتية

html
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700&display=swap"
/>

علاوة على ذلك، باستخدام next/font (Next.js 13+)، يمكنك معالجة الخطوط أثناء وقت البناء، مما يلغي الحاجة إلى الطلبات الخارجية.

js
// app/layout.js
import { Noto_Sans_KR } from 'next/font/google';

const notoSansKR = Noto_Sans_KR({
  weight: ['400', '700'],
  subsets: ['latin'],
  display: 'swap',
});

بعد تحسين الخطوط، انخفض LCP من 1.8 ثانية إلى 1.5 ثانية.

الطريقة 3 — تقسيم الشيفرة وتحسين الحزمة

إذا كانت حزمة JS الرئيسية كبيرة، فإن خيط المتصفح الرئيسي ينشغل بالتحليل والتنفيذ. خلال هذه الفترة، لا يتم رسم عنصر LCP على الشاشة.

تقسيم الحزمة الأولية باستخدام التحميل الديناميكي

jsx
import dynamic from 'next/dynamic';

// مكون الرسم البياني الثقيل الذي يقع أسفل التمرير
const SalesChart = dynamic(() => import('@/components/SalesChart'), {
  ssr: false,
  loading: () => <div className="chart-skeleton" />, 
});

تحليل الحزمة لإزالة المكتبات غير الضرورية

bash
npx @next/bundle-analyzer

أظهر التحليل أن moment.js (66 كيلوبايت مضغوط) وlodash بالكامل (70 كيلوبايت مضغوط) كانا مدرجين. تم استبدال moment بوظائف date-fns المطلوبة فقط، وتم تحويل lodash إلى استيراد تقليم الشجرة من lodash-es.

js
// قبل
import _ from 'lodash';
const result = _.groupBy(data, 'category');

// بعد
import { groupBy } from 'lodash-es';
const result = groupBy(data, 'category');

انخفض حجم الحزمة الرئيسية من 1.8 ميغابايت إلى 420 كيلوبايت، وانخفض LCP من 1.5 ثانية إلى 1.2 ثانية.


خفض CLS من 0.28 إلى 0.04

كان السبب الرئيسي في حركة التخطيط في مكانين.

1. صور بدون حجم محدد

يجب تحديد width وheight لجميع علامات ، أو تثبيت aspect-ratio باستخدام CSS.

css
.product-image-wrapper {
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

2. لافتات الإعلانات التي تم إدراجها في وقت متأخر

تم وضع عنصر نائب بنفس الارتفاع قبل تحميل فتحة الإعلان.

jsx
<div style={{ minHeight: '90px' }}>
  <AdBanner slot="header" />
</div>

بهذه الخطوتين فقط، انخفض CLS من 0.28 إلى 0.04.


تحسين INP — تقليل عبء الخيط الرئيسي

تحسن INP بشكل طبيعي بعد تقليل حجم الحزمة من 320 مللي ثانية إلى 140 مللي ثانية. بالإضافة إلى ذلك، قمت بتأجيل العمليات الثقيلة التي كانت تُنفذ بشكل متزامن داخل معالج أحداث النقر باستخدام requestIdleCallback.

js
button.addEventListener('click', () => {
  // تحديث واجهة المستخدم الفوري المطلوب
  setLoading(true);

  // تأجيل المعالجة الثقيلة إلى وقت الفراغ
  requestIdleCallback(() => {
    processHeavyData(payload);
  });
});

مقارنة قبل وبعد التحسين

المؤشرقبل التحسين

🔧 Related Free Tools

ذو صلة