في ٢٠٢٥ لم تعد الكور ويب فايتلز مجرد أرقام في تقرير ليتهوس، بل أصبحت بوصلة حقيقية لتجربة المستخدم. اكتشف كيف تغيرت المقاييس، ما الذي بقي ثابتاً، ولماذا لا يزال المطورون يكافحون لتحقيقها تحت ضغط الأداء الحقيقي.
في صيف ٢٠٢٤، أطلقنا منصة جديدة بالكامل لشركة تجارة إلكترونية كبرى في الشرق الأوسط. بعد أسبوعين من الإطلاق، جاءني تقرير ليتهوس مفزع: ٣٨٪ من المستخدمين يغادرون الصفحة قبل أن يكتمل تحميلها بالكامل. المشكلة؟ لم تكن سرعة التحميل هي العائق الوحيد، بل كانت تجربة التفاعل نفسها — الأزرار التي لا تستجيب، الصور التي تقفز فجأة، والنصوص التي تختفي ثم تظهر بعد ثوانٍ. حينها أدركت أن الكور ويب فايتلز لم تعد مجرد مجموعة من الأرقام التي نضعها في تقرير الأداء الشهري، بل أصبحت مؤشراً حقيقياً على مدى نجاح أو فشل المنتج الرقمي. السؤال الذي يطرح نفسه الآن: هل تطورت هذه المقاييس في ٢٠٢٥ لتصبح أكثر ذكاءً، أم أنها أصبحت مجرد عقبة أخرى في طريق المطورين؟
الحقيقة المؤلمة هي أن معظم الفرق التقنية لا تزال تعامل الكور ويب فايتلز كهدف يجب تحقيقه في نهاية المشروع، وليس كمبدأ أساسي يجب تصميم النظام حوله منذ البداية. في هذا المقال، سنفكك ما تغير في هذه المقاييس خلال العامين الماضيين، لماذا لا تزال بعض الفرق تكافح لتحقيقها رغم التقدم التكنولوجي، وكيف يمكن للمطورين أن يتخطوا هذه العقبات دون التضحية بجودة الكود أو تجربة المستخدم.
في عام ٢٠٢٠، عندما أطلقت جوجل الكور ويب فايتلز كمقاييس رسمية، كانت الفكرة بسيطة: قياس ثلاث جوانب رئيسية لتجربة المستخدم — تحميل الصفحة (LCP)، استجابة التفاعل (FID)، واستقرار المحتوى (CLS). لكن في ٢٠٢٥، تغيرت اللعبة بالكامل. لم تعد هذه المقاييس تقيس مجرد لحظات منعزلة في تجربة المستخدم، بل أصبحت جزءاً من نظام أوسع وأكثر تعقيداً يشمل الذكاء الاصطناعي، تحليل سلوك المستخدم في الوقت الفعلي، وحتى توقعات الأداء بناءً على نوع الجهاز واتصال الشبكة.
أهم التغييرات التي طرأت على الكور ويب فايتلز في ٢٠٢٥ هي دمجها مع ما يسمى بـ "الذكاء السياقي" Contextual Intelligence. الآن، بدلاً من قياس LCP بشكل ثابت عند ٢.٥ ثانية، يأخذ النظام في الاعتبار نوع الصفحة (هل هي صفحة منتج؟ صفحة مقالة؟)، نوع الجهاز (هل هو هاتف قديم أم جهاز لوحي حديث؟)، وحتى نوع الاتصال (٣G مقابل ٥G). هذا يعني أن نفس الصفحة قد تحصل على تقييم مختلف تماماً بناءً على السياق، وهو ما يجعل تحقيق "الدرجة الخضراء" في ليتهوس أكثر تعقيداً — أو ربما أكثر عدالة — من ذي قبل.
في السابق، كان Largest Contentful Paint يقيس ببساطة الوقت الذي يستغرقه أكبر عنصر مرئي (عادة صورة أو نص كبير) ليظهر على الشاشة. لكن في ٢٠٢٥، تغير تعريف "الأكبر" تماماً. الآن، يأخذ LCP في الاعتبار ليس فقط حجم العنصر، بل أيضاً أهميته الوظيفية. مثلاً، إذا كان العنصر الأكبر هو صورة خلفية غير ضرورية لتجربة المستخدم، فقد يتم تجاهله لصالح عنصر أصغر لكنه أكثر أهمية مثل زر "اشترِ الآن". هذا التغيير جاء بعد دراسات أظهرت أن المستخدمين يهتمون أكثر بعناصر التفاعل الرئيسية بدلاً من العناصر الزخرفية، حتى لو كانت أكبر حجماً.
من الناحية التقنية، هذا يعني أن المطورين يجب أن يعيدوا التفكير في كيفية تحميل الموارد. مثلاً، بدلاً من تحميل جميع الصور دفعة واحدة، يمكن استخدام تقنيات مثل Priority Hints لتحديد أولوية تحميل العناصر الأكثر أهمية أولاً. إليك مثال عملي على كيفية تحقيق ذلك:
<!DOCTYPE html>
<html>
<head>
<link rel="preload" href="hero-image.jpg" as="image" importance="high">
<link rel="preload" href="product-button.svg" as="image" importance="high">
</head>
<body>
<img src="hero-image.jpg" alt="Hero Image" loading="eager" fetchpriority="high">
<button>
<img src="product-button.svg" alt="Buy Now" loading="eager" fetchpriority="high">
</button>
<img src="background.jpg" alt="Background" loading="lazy" fetchpriority="low">
</body>
</html>لاحظ كيف استخدمنا `fetchpriority="high"` لتحديد أولوية تحميل العناصر الأساسية، بينما تركنا العناصر الثانوية لتحميل متأخر باستخدام `loading="lazy"`. هذا النوع من التحسينات لم يكن ضرورياً في الماضي، لكن في ٢٠٢٥ أصبح جزءاً أساسياً من استراتيجية الأداء.
في مارس ٢٠٢٤، أعلنت جوجل أن First Input Delay (FID) سيحل محله Interaction to Next Paint (INP) كمقياس رسمي في الكور ويب فايتلز. هذا التغيير لم يكن مجرد تعديل بسيط في الاسم، بل كان تحولاً جذرياً في كيفية قياس استجابة الصفحة. بينما كان FID يقيس فقط التأخير الأولي للاستجابة لأول تفاعل، يقيس INP استجابة جميع التفاعلات خلال جلسة المستخدم بالكامل، ثم يختار أسوأ ٥٪ منها لتقييم الأداء.
لماذا هذا التغيير مهم؟ لأن FID كان يعطي انطباعاً خاطئاً عن الأداء. مثلاً، قد تحصل صفحة على درجة ممتازة في FID لأنها استجابت بسرعة للتفاعل الأول، لكن بعدها تصبح بطيئة جداً في التفاعلات اللاحقة. هذا بالضبط ما حدث في منصة التجارة الإلكترونية التي ذكرت سابقاً — كانت الأزرار تستجيب بسرعة في البداية، لكن بعد تحميل جميع سكربتات الطرف الثالث، أصبحت الصفحة تتجمد عند كل نقرة. INP كشف هذه المشكلة بوضوح، مما أجبرنا على إعادة هيكلة كيفية تحميل وتنفيذ الجافا سكريبت.
// مثال على تحسين INP باستخدام Web Workers لتقليل تحميل الـ Main Thread
const workerCode = `
self. function(e) {
// معالجة ثقيلة هنا بعيداً عن الـ Main Thread
const result = heavyComputation(e.data);
postMessage(result);
};
function heavyComputation(data) {
// محاكاة عملية حسابية معقدة
let sum = 0;
for (let i = 0; i < 1e8; i++) {
sum += Math.sqrt(i);
}
return sum;
}
`;
const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
// عند الحاجة للمعالجة الثقيلة
worker.postMessage({ /* البيانات */ });
worker.onmessage = function(e) {
// تحديث الـ UI بعد الانتهاء
updateUI(e.data);
};
// تجنب حظر الـ Main Thread
function updateUI(data) {
requestAnimationFrame(() => {
document.getElementById('result').textContent = data;
});
}في هذا المثال، استخدمنا Web Workers لنقل العمليات الثقيلة بعيداً عن الـ Main Thread، مما يسمح للواجهة بالاستجابة بسرعة حتى أثناء معالجة البيانات المعقدة. هذا النوع من التحسينات أصبح ضرورياً لتحقيق درجات جيدة في INP، خاصة في التطبيقات التي تعتمد بشكل كبير على الجافا سكريبت مثل تطبيقات الويب التقدمية (PWAs) والمنصات التفاعلية.
Cumulative Layout Shift (CLS) كان دائماً المقياس الأكثر غموضاً بين الكور ويب فايتلز. في السابق، كان يقيس ببساطة مقدار تحرك العناصر على الصفحة أثناء التحميل. لكن في ٢٠٢٥، أصبح CLS أكثر ذكاءً — فهو الآن يأخذ في الاعتبار ليس فقط مقدار التحرك، بل أيضاً تأثيره النفسي على المستخدم. مثلاً، تحرك صورة صغيرة في الزاوية قد لا يؤثر كثيراً، لكن تحرك زر رئيسي في منتصف الصفحة يمكن أن يسبب إحباطاً كبيراً للمستخدم، حتى لو كان التحرك بسيطاً.
أحد أكبر التحديات التي واجهناها مع CLS في المشاريع الحديثة هو إعلانات الطرف الثالث. حتى لو حجزنا مساحة للإعلانات مسبقاً باستخدام `aspect-ratio`، فإن بعض شبكات الإعلانات لا تزال تتجاهل هذه المساحة وتحمّل إعلانات بأحجام مختلفة، مما يسبب تحركاً مفاجئاً في الصفحة. الحل الذي وجدناه فعالاً هو استخدام ما يسمى بـ "الاحتياطيات الذكية" Smart Reserves، وهي تقنية تجمع بين CSS و JavaScript لضمان بقاء المساحة محجوزة حتى بعد تحميل الإعلان.
/* استخدام aspect-ratio مع احتياطي ذكي */
.ad-container {
aspect-ratio: 16 / 9;
min-height: 0; /* منع التمدد غير المتوقع */
contain: layout; /* تحسين الأداء */
position: relative;
background: #f0f0f0; /* لون خلفية مؤقت */
}
.ad-placeholder {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #666;
font-size: 0.8rem;
}
/* عند تحميل الإعلان بنجاح */
.ad-loaded .ad-placeholder {
display: none;
}// مراقبة تحميل الإعلانات ومنع CLS
const adC document.querySelectorAll('.ad-container');
adContainers.forEach(container => {
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
// إذا تغير حجم الإعلان بعد التحميل، قم بإعادة ضبط المساحة
if (entry.contentRect.height > entry.target.clientHeight) {
entry.target.style.minHeight = `${entry.contentRect.height}px`;
}
}
});
observer.observe(container);
// تحميل الإعلان ديناميكياً
const adScript = document.createElement('script');
adScript.src = 'https://example.com/ad-script.js';
adScript.async = true;
adScript.onload = () => {
container.classList.add('ad-loaded');
};
container.appendChild(adScript);
});هذا النهج يضمن أن المساحة تبقى محجوزة حتى بعد تحميل الإعلان، مما يمنع حدوث أي تحرك مفاجئ في الصفحة. بالإضافة إلى ذلك، استخدمنا `ResizeObserver` لمراقبة أي تغييرات في حجم الإعلان بعد التحميل، مما يسمح لنا بضبط المساحة ديناميكياً إذا لزم الأمر.
رغم كل التطورات في الكور ويب فايتلز، هناك بعض المبادئ الأساسية التي لم تتغير. أولاً، لا يزال حجم الموارد هو العامل الأكبر في أداء الصفحة. في عام ٢٠٢٣، كان متوسط حجم صفحة الويب حوالي ٢.٥ ميجابايت. في ٢٠٢٥، ارتفع هذا الرقم إلى ٣.٨ ميجابايت، ومع ذلك لا تزال الصفحات التي تقل عن ١ ميجابايت تحقق أفضل أداء. هذا يعني أن تقنيات مثل ضغط الصور (WebP/AVIF)، وتقسيم الكود Code Splitting، وتأخير تحميل الموارد غير الضرورية (Lazy Loading) لا تزال ضرورية كما كانت في الماضي.
ثانياً، لا يزال الـ Critical Rendering Path هو المفتاح لتحقيق أداء جيد. في كل مشروع عملنا عليه خلال العامين الماضيين، كانت الخطوة الأولى دائماً هي تحليل هذا المسار وتحديد الموارد التي تعيق عرض الصفحة. حتى مع ظهور تقنيات مثل Server Components في Next.js و Islands Architecture في Astro، لا تزال فكرة تحديد الأولويات في تحميل الموارد هي الأساس الذي نبني عليه كل شيء آخر.
في قلب كل مشكلة أداء تكمن نفس الآلية القديمة: الـ Event Loop. في ٢٠٢٥، أصبح لدينا المزيد من الأدوات لتحسين كيفية عمل هذا الـ Loop، لكن المبادئ الأساسية لم تتغير. لا يزال حظر الـ Main Thread هو السبب الرئيسي لتجارب المستخدم البطيئة، سواء كان ذلك بسبب سكربتات الطرف الثالث، أو عمليات حسابية ثقيلة، أو حتى معالجة DOM بشكل غير فعال.
أحد أكبر الأخطاء التي أراها في المشاريع الحديثة هو الاعتماد المفرط على المكتبات الضخمة مثل React بدون فهم كيفية تأثيرها على الـ Event Loop. مثلاً، إعادة الـ Render الكاملة عند كل تغيير بسيط في الـ State يمكن أن تتسبب في تجمد الصفحة تماماً، خاصة على الأجهزة المنخفضة الأداء. الحل؟ استخدام تقنيات مثل Memoization، و Virtualization، وتقسيم الواجهة إلى مكونات أصغر وأكثر استقلالية.
// تحسين أداء React باستخدام memo و useCallback
import React, { memo, useCallback, useMemo } from 'react';
const ExpensiveComp memo(({ data, onAction }) => {
// هذا المكون لن يعاد رندره إلا إذا تغيرت props
const processedData = useMemo(() => {
return data.map(item => heavyProcessing(item));
}, [data]);
return (
<div>
{processedData.map(item => (
<Item key={item.id} item={item} onClick={onAction} />
))}
</div>
);
});
function ParentComponent() {
const [count, setCount] = React.useState(0);
// استخدام useCallback لمنع إعادة إنشاء الدالة عند كل رندر
const handleAction = useCallback((id) => {
console.log('Action on:', id);
}, []);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Increment: {count}</button>
<ExpensiveComponent data={largeDataSet} onAction={handleAction} />
</div>
);
}
function heavyProcessing(item) {
// محاكاة عملية حسابية ثقيلة
let result = 0;
for (let i = 0; i < 1e6; i++) {
result += Math.sqrt(item.value * i);
}
return { ...item, processed: result };
}في هذا المثال، استخدمنا `memo` لمنع إعادة الـ Render غير الضرورية، و `useMemo` لتجنب إعادة حساب البيانات الثقيلة، و `useCallback` لمنع إعادة إنشاء الدوال. هذه التقنيات البسيطة يمكن أن تحدث فرقاً كبيراً في أداء التطبيقات المعقدة، خاصة على الأجهزة المنخفضة الأداء.
في نهاية المطاف، لا يزال الكثير من المطورين ينظرون إلى الكور ويب فايتلز كعقبة يجب تجاوزها بدلاً من فرصة لتحسين تجربة المستخدم. الحقيقة هي أن هذه المقاييس، رغم تعقيداتها، ليست سوى انعكاس لمبادئ أساسية في هندسة البرمجيات: الكفاءة، والاستجابة، والاستقرار. المشكلة ليست في المقاييس نفسها، بل في كيفية تعامل الفرق معها — هل هي مجرد أرقام يجب تحقيقها في نهاية المشروع، أم هي مبادئ يجب تصميم النظام حولها منذ البداية؟
في تجربتي، الفرق التي تحقق أفضل أداء هي تلك التي تدمج تحسينات الكور ويب فايتلز في كل مرحلة من مراحل التطوير، بدءاً من التصميم وحتى النشر. مثلاً، بدلاً من انتظار نهاية المشروع لتحليل الأداء، يمكن استخدام أدوات مثل Lighthouse CI في كل مرحلة من مراحل الـ CI/CD Pipeline لضمان عدم تراكم المشاكل. بالإضافة إلى ذلك، يمكن استخدام تقنيات مثل Server-Side Rendering (SSR) و Static Site Generation (SSG) منذ البداية لتقليل الاعتماد على الجافا سكريبت في الـ Client Side.
إذا كان هناك درس واحد تعلمته من العمل على عشرات المشاريع خلال العامين الماضيين، فهو هذا: لا تعامل الكور ويب فايتلز كمقاييس يجب تحقيقها، بل تعامل معها كبوصلة توجه قراراتك الهندسية. بدلاً من التركيز على تحقيق "الدرجة الخضراء" في ليتهوس، ركز على فهم السبب وراء كل مشكلة أداء وحلها من جذورها. مثلاً، إذا كان LCP بطيئاً، لا تكتفِ بضغط الصور، بل اسأل: لماذا يتم تحميل هذه الصورة أصلاً؟ هل هي ضرورية في هذه الصفحة؟ هل يمكن استبدالها بصورة أصغر أو SVG؟ هل يمكن تحميلها بعد عرض المحتوى الرئيسي؟
في ٢٠٢٥، أصبح أداء الويب أكثر تعقيداً من أي وقت مضى، لكن المبادئ الأساسية لا تزال هي نفسها. إذا أردت بناء تجارب رقمية سريعة ومستقرة، ابدأ بفهم كيفية عمل المتصفح، وكيفية تأثير كل سطر من الكود على تجربة المستخدم، وكيفية قياس هذا التأثير بدقة. الكور ويب فايتلز ليست مجرد أرقام — إنها لغة مشتركة بين المطورين والمتصفحات والمستخدمين، وإذا تعلمت كيف تتحدث هذه اللغة، ستتمكن من بناء تجارب رقمية لا تُنسى.