Skip to content

قياس أداء الويب وتحسينه

🎯 السؤال الأساسي

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


1. لماذا "تحسين الأداء"؟

1.1 من قابل للاستخدام إلى جيد: تطور تحسين الأداء

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

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

👴 صفحات الويب قبل عشر سنوات

  • الصفحة الواحدة بضعة كيلوبايتات إلى عشرات الكيلوبايتات فقط
  • تحتوي فقط على نصوص وعدد قليل من الصور
  • لا يشعر المستخدم تقريبًا بأي تأخير في التحميل
  • لا حاجة لأي تحسين للأداء

🚀 صفحات الويب الحديثة

  • الصفحة الواحدة قد تصل إلى عدة ميغابايتات أو أكثر
  • تحتوي على صور عالية الدقة وفيديوهات ومكونات تفاعلية
  • تحميل بطيء، تمرير متقطع، استجابة بطيئة للنقر
  • يجب تحسين الأداء لتكون قابلة للاستخدام

هذه هي المشكلة التي يحلها "تحسين الأداء": جعل وقت انتظار المستخدم أقصر، وجعل العمليات أكثر سلاسة.

1.2 قصة حقيقية عن الوقوع في المشاكل: لماذا تحتاج إلى فهم تحسين الأداء

قد تقول: "الإنترنت الآن سريع جدًا، والأجهزة جيدة جدًا، هل ما زلنا بحاجة للتفكير في تحسين الأداء؟" دعني أحكي لك قصة حقيقية، وستفهم لماذا هذه المعرفة مهمة جدًا.

قصة شياو وانغ مع مشاكل الأداء

شياو وانغ هو مهندس واجهة أمامية جديد في الشركة، مسؤول عن تطوير الصفحة الرئيسية للمتجر الإلكتروني. استخدم أحدث إصدار من Vue 3، وأشهر مكتبة UI، واكتملت الوظائف بشكل ممتاز، وكان كل شيء طبيعيًا عند اختباره على حاسوبه عالي الأداء في الشركة.

لكن في اليوم التالي بعد الإطلاق، انفجر قسم خدمة العملاء — اشتكى عدد كبير من المستخدمين من أن "الموقع بطيء جدًا"، "الصور لا تظهر"، "النقر على الأزرار لا يستجيب لفترة طويلة". فتح شياو وانغ جهاز التطوير الخاص به للاختبار، وكان كل شيء سلسًا جدًا، ولم يفهم أين تكمن المشكلة على الإطلاق.

لاحقًا، طلب المساعدة من معلمه، فطلب منه المعلم استخدام حاسوب محمول عادي، والاتصال بشبكة 4G عادية، ثم اختبار موقعه. عندها فقط صُدم شياو وانغ: استغرق تحميل الصفحة الرئيسية أكثر من عشر ثوانٍ، وكان التمرير في القائمة متقطعًا مثل عرض PowerPoint، وكان النقر على الأزرار يستغرق عدة ثوانٍ للاستجابة.

اتضح أن بيئة تطوير شياو وانغ كانت MacBook Pro فاخر + ألياف بصرية بسرعة جيجابت، بينما يستخدم معظم المستخدمين أجهزة عادية + شبكة محمولة. كان في كوده عشرات الصور عالية الدقة غير المضغوطة، واستورد مكتبة UI بأكملها لكنه استخدم فقط بضعة مكونات، وقام بالكثير من الحسابات المتزامنة أثناء العرض.

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

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

💡 الدرس الأساسي

تحسين الأداء ليس خيارًا، بل مهارة ضرورية. يجب أن تفكر من منظور المستخدم — فهم يستخدمون أجهزة عادية وشبكات عادية، وإذا كان كودك لا يعمل على أجهزتهم، فهذا يعني أنك بحاجة إلى التحسين.


2. المفاهيم الأساسية: التحميل، والعرض، والتفاعل

🤔 ما علاقة هذه المفاهيم بالأداء؟

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

عندما يزور المستخدم صفحتك، يمر بالترتيب التالي:

  1. التحميل → تنزيل HTML/CSS/JS/الصور من الخادم إلى المتصفح
  2. العرض → "رسم" المحتوى الذي تم تنزيله إلى صفحة يمكن للمستخدم رؤيتها
  3. التفاعل → الاستجابة لنقرات المستخدم وتمريره وعملياته الأخرى

لذلك، تحسين الأداء هو جعل هذه الروابط الثلاثة أسرع. بفهمها، ستعرف أين تكمن عنق الزجاجة في الأداء، وما الطريقة المناسبة للتحسين.

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

2.1 فهم الروابط الثلاثة باستخدام تشبيه المطعم

تخيل أنك تذهب إلى مطعم لتناول الطعام، هذه العملية تشبه بشكل مذهل زيارة صفحة الويب:

الرابط🍽️ تشبيه المطعمالوظيفة الفعليةمثال ملموس
التحميلنقل المكونات من المستودع إلى المطبختنزيل HTML/CSS/JS/الصور من الخادم إلى المتصفحيفتح المستخدم صفحة الويب، ويبدأ المتصفح في تنزيل الموارد المختلفة
العرضيقوم الطاهي بتحويل المكونات إلى أطباقيحول المتصفح الكود إلى صفحة يمكن للمستخدم رؤيتهايحلل المتصفح HTML ويحسب التخطيط ويرسم الصفحة
التفاعليستجيب النادل لطلبات الزبونيستجيب المتصفح للنقر والتمرير والعمليات الأخرىينقر المستخدم على زر، وتستجيب الصفحة

2.2 التحميل (Loading): نقل المكونات

التحميل هو عملية تنزيل الموارد المختلفة التي تحتاجها صفحة الويب (HTML، CSS، JavaScript، الصور، الخطوط، إلخ) من الخادم إلى المتصفح. هذه العملية تشبه نقل المكونات من المستودع إلى المطبخ، إذا كان النقل بطيئًا أو كانت المكونات كثيرة جدًا، فسيضطر المطبخ للانتظار.

لماذا يكون التحميل بطيئًا؟ هناك ثلاثة أسباب رئيسية: أولاً، حجم الموارد كبير جدًا — صورة واحدة عالية الدقة غير مضغوطة قد تصل إلى 5MB، وهذا يعادل تنزيل رواية كاملة؛ ثانيًا، تأخير الشبكة — إذا كان الخادم في الخارج، أو كان المستخدم يستخدم شبكة محمولة، فسيستغرق كل طلب وقتًا طويلاً؛ أخيرًا، الطلبات كثيرة جدًا — عدد الموارد التي يمكن للمتصفح تنزيلها في نفس الوقت محدود، والموارد الكثيرة جدًا ستضطر للانتظار في الطابور.

🔍 انظر ماذا يحدث في مرحلة التحميل

عندما يدخل المستخدم عنوان URL في شريط العناوين ويضغط Enter، تحدث الأمور التالية بالترتيب:

  1. تحليل DNS: تحويل اسم النطاق (مثل www.example.com) إلى عنوان IP (مثل 192.168.1.1)، مثل البحث عن عنوان المطعم في دليل الهاتف
  2. اتصال TCP: إنشاء اتصال بين المتصفح والخادم، مثل طلب الرقم قبل الاتصال
  3. مصافحة TLS: إنشاء اتصال آمن (HTTPS)، مثل تأكيد هوية الطرف الآخر
  4. طلب الموارد: يطلب المتصفح ملف HTML من الخادم
  5. تحليل HTML: يحلل المتصفح HTML، ويكتشف الحاجة إلى CSS وJS والصور وغيرها من الموارد، ويستمر في الطلب
  6. تنزيل الموارد: تنزيل جميع الموارد المطلوبة محليًا
  7. بدء العرض: بعد اكتمال التنزيل، يبدأ عرض الصفحة

الخطوات من 1 إلى 4 تسمى "وقت البايت الأول" (TTFB)، والخطوات من 5 إلى 7 هي وقت تنزيل الموارد الفعلي.

وسائل تحسين التحميل الشائعة:

  • ضغط الموارد: تصغير حجم الملفات (ضغط Gzip و Brotli)
  • استخدام CDN: تخزين الملفات على خوادم أقرب إلى المستخدم
  • التحميل الكسول: تحميل المحتوى الذي يراه المستخدم فقط، والباقي يتم تحميله عند التمرير
  • تقسيم الكود: تقسيم الملفات الكبيرة إلى ملفات صغيرة، وتحميلها حسب الحاجة

2.3 العرض (Rendering): الطاهي يطبخ

العرض هو عملية تحويل المتصفح لـ HTML وCSS وJavaScript التي تم تنزيلها إلى صفحة يمكن للمستخدم رؤيتها. هذه العملية تشبه قيام الطاهي بتحويل المكونات إلى أطباق، إذا كانت عملية الطهي معقدة والخطوات كثيرة، فسيتأخر تقديم الطعام.

📖 ما هو "العرض"؟

ربما سمعت بمصطلح "العرض"، ما هو بالضبط؟

ببساطة، العرض هو عملية تحويل الكود إلى صورة.

المهام التي يقوم بها المتصفح تشمل:

  1. تحليل HTML → إنشاء شجرة DOM (هيكل الصفحة)
  2. تحليل CSS → إنشاء شجرة CSSOM (أنماط الصفحة)
  3. الدمج → إنشاء شجرة العرض (دمج الهيكل والأنماط)
  4. التخطيط → حساب موضع وحجم كل عنصر
  5. الرسم → رسم العناصر
  6. التركيب → دمج الطبقات المتعددة في الصورة النهائية

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

لماذا يكون العرض بطيئًا؟ هناك سببان رئيسيان: أولاً، الصفحة معقدة جدًا — إذا كانت الصفحة تحتوي على عشرات الآلاف من عقد DOM، فسيستغرق حساب التخطيط والرسم وقتًا طويلاً جدًا؛ ثانيًا، التعديل المتكرر للصفحة — إذا كان كود JavaScript يعدل DOM بشكل متكرر، فسيؤدي ذلك إلى إعادة التخطيط والرسم بشكل متكرر، مما يستهلك أداءً كبيرًا.

📁 انظر ماذا يحدث في مرحلة العرض

المسار الكامل للعرض:

HTML (نص)

[تحليل HTML] → إنشاء شجرة DOM

شجرة DOM (هيكل الصفحة)

CSS (ورقة الأنماط)

[تحليل CSS] → إنشاء شجرة CSSOM

شجرة CSSOM (أنماط الصفحة)

شجرة DOM + شجرة CSSOM

[الدمج] → إنشاء شجرة العرض

شجرة العرض (العناصر المراد عرضها)

[التخطيط Layout] → حساب موضع وحجم كل عنصر

[الرسم Paint] → ملء الألوان ورسم النصوص

[التركيب Composite] → دمج الطبقات المتعددة

الصورة النهائية

مسار العرض الحرج (Critical Rendering Path): يجب على المتصفح عرض محتوى الشاشة الأولى بأسرع وقت ممكن، ليشعر المستخدم أن "الموقع سريع". هذا يسمى "تحسين مسار العرض الحرج".

👇 جرب بنفسك: العرض التوضيحي التالي يوضح كيف يقوم المتصفح بعرض الصفحة. انقر على "التالي"، ولاحظ مراحل العرض المختلفة:

Frontend Performance Optimization Map
Select a dimension to explore bottlenecks and matching optimization techniques.

⚠️ Common Bottlenecks

  • Large assets
    Images and JS bundles are not compressed, so downloads take longer.
  • Too many requests
    HTTP/1.1 head-of-line blocking makes resources wait in line.
  • Network latency
    The server is physically far away, increasing RTT.
How to fix it?

🚀 Solutions

  • Asset compression
    Use Gzip/Brotli and image formats such as WebP.
    Smaller size
  • Lazy loading
    Load only resources visible in the current viewport.
    Smaller sizeFewer requests
  • CDN acceleration
    Distribute assets to nodes close to users.
    Shorter distance
  • HTTP caching
    Use browser cache to avoid repeated requests.
    Fewer requests

Core goal: Deliver resources to the browser faster by reducing size, request count, and distance.

وسائل تحسين العرض الشائعة:

  • تقليل إعادة التخطيط وإعادة الرسم: تجنب تعديل DOM بشكل متكرر، واستخدام transform و opacity بدلاً من top و width
  • القوائم الافتراضية: عرض محتوى المنطقة المرئية فقط، تحسن الأداء بشكل ملحوظ مع البيانات الكبيرة
  • رسوم CSS المتحركة: استخدام رسوم CSS المتحركة بدلاً من رسوم JavaScript المتحركة، أداء أفضل

2.4 التفاعل (Interaction): استجابة النادل

التفاعل هو عملية استجابة المتصفح لعمليات المستخدم (النقر، التمرير، الإدخال، إلخ). هذه العملية تشبه استجابة النادل لطلبات الزبون، إذا كان النادل مشغولاً جدًا، فسيضطر الزبون للانتظار.

لماذا يكون التفاعل متقطعًا؟ السبب الرئيسي هو أن الخيط الرئيسي محظور. JavaScript في المتصفح أحادي الخيط، إذا كان الكود ينفذ حسابات معقدة، فلن يتمكن من الاستجابة لعمليات المستخدم، مما يؤدي إلى توقف الصفحة.

🤔 ما هو "الخيط الرئيسي"؟

المتصفح لديه عدة خيوط، لكن المسؤول عن تنفيذ JavaScript وعرض الصفحة والاستجابة لعمليات المستخدم هو خيط واحد فقط — الخيط الرئيسي.

يمكنك تخيل الخيط الرئيسي على أنه نادل مشغول، عليه القيام بالعديد من المهام:

  • تنفيذ كود JavaScript (حساب البيانات، استدعاء API)
  • عرض الصفحة (التخطيط، الرسم)
  • الاستجابة لعمليات المستخدم (النقر على الأزرار، تمرير الصفحة)

المشكلة هي: لديه شخص واحد فقط. إذا كان ينفذ حسابات JavaScript معقدة (مثل معالجة عشرة آلاف سجل بيانات)، وفي هذا الوقت نقر المستخدم على زر، فلن يتمكن من الاستجابة فورًا، ويجب عليه الانتظار حتى انتهاء الحساب. هذا هو أصل التوقف.

الحلول:

  • نقل الحسابات المعقدة إلى Web Worker (خيط خلفي)
  • استخدام تقسيم الوقت، وتقسيم المهام الكبيرة إلى مهام صغيرة
  • تجنب العمليات المتزامنة المعقدة، واستخدام العمليات غير المتزامنة بدلاً منها

👇 جرب بنفسك: العرض التوضيحي التالي يقارن بين الحساب المتزامن وWeb Worker. انقر على "بدء الحساب"، ولاحظ ما إذا كانت الصفحة تتوقف:

📊Core Web VitalsAdjust load time and observe how performance metrics change.
FCP
First Contentful Paint
0.8 s
First contentful paint
Good
LCP
Largest Contentful Paint
1.8 s
Largest contentful paint
Good
FID
First Input Delay
200 ms
First input delay
Needs improvement
CLS
Cumulative Layout Shift
0.15
Cumulative layout shift
Needs improvement
Good
Needs improvement
Poor
💡Core metrics:FCP ≤ 1.8s, LCP ≤ 2.5s, FID ≤ 100ms, and CLS ≤ 0.1. The goal is to keep every metric in the "Good" range.

وسائل تحسين التفاعل الشائعة:

  • منع الاهتزاز والتحكم في التدفق: تقييد تكرار تشغيل الأحداث (مثل أحداث التمرير والإدخال)
  • Web Worker: نقل الحسابات المعقدة إلى خيط خلفي، دون حظر الخيط الرئيسي
  • تقسيم الوقت: تقسيم المهام الكبيرة إلى مهام صغيرة، لإتاحة الفرصة للمتصفح للاستجابة لعمليات المستخدم

3. تطبيق عملي: رحلة تطور تحسين الأداء لفريق

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

3.1 الصورة الشاملة للتطور

الجدول التالي يوضح المراحل الأربع لتحسين الأداء، ويمكنك رؤية كيف تطورت وسائل التحسين والأدوات والمؤشرات خطوة بخطوة:

المرحلةوسائل التحسينأدوات المراقبةالمؤشرات الأساسيةالتغيير الأساسي
المرحلة الأولى: العصر البدائيلا شيء (لم يتم التفكير)لا شيء (بالشعور)لا شيءلا وعي بالأداء على الإطلاق، المهم أن يعمل
المرحلة الثانية: التحسين اليدويضغط الصور، تقليل الطلباتلوحة Network في المتصفحوقت تحميل الصفحةبداية الوعي، لكن الطرق بدائية
المرحلة الثالثة: التحسين المنهجيتقسيم الكود، التحميل الكسول، القوائم الافتراضيةLighthouse، لوحة PerformanceFCP، LCP، TBTاستخدام أدوات احترافية، مع أهداف تحسين واضحة
المرحلة الرابعة: التحسين المستمرميزانية الأداء، فحص CI/CDRUM، Lighthouse CIINP، CLS، مراقبة شاملةدمج الأداء في سير عمل التطوير

📊 ماذا يمكنك أن ترى من الجدول؟

لنقرأ هذا الجدول سطرًا بسطر:

المرحلة الأولى → المرحلة الثانية: من "لا وعي" إلى "وعي". هذه خطوة حاسمة — يبدأ المطور في إدراك أن الأداء مشكلة، ويحاول التحسين. لكن وسائل التحسين بدائية نسبيًا، تعتمد بشكل أساسي على الشعور والخبرة.

المرحلة الثانية → المرحلة الثالثة: من "يدوي" إلى "منهجي". هذه نقلة نوعية — البدء في استخدام أدوات احترافية (Lighthouse، لوحة Performance) لتشخيص مشاكل الأداء، واستخدام طرق علمية (تقسيم الكود، التحميل الكسول) للتحسين، بدلاً من الاعتماد على الشعور.

المرحلة الثالثة → المرحلة الرابعة: من "تحسين لمرة واحدة" إلى "تحسين مستمر". عندما يصبح تحسين الأداء جزءًا من سير عمل التطوير، يصبح من الضروري إنشاء نظام مراقبة (RUM، مراقبة المستخدم الحقيقي)، ووضع ميزانية أداء في مرحلة التطوير لمنع التراجع.

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

3.2 المرحلة الأولى: العصر البدائي — لم يتم التفكير على الإطلاق

لماذا سمي "العصر البدائي"؟ لأن هذه المرحلة لم تفكر في مشكلة الأداء على الإطلاق — المهم أن يعمل. الفريق كان مكونًا من 3 أشخاص فقط، يعملون على موقع شركة بسيط، المشروع صغير جدًا، ولا توجد مشاكل ظاهرة.

لكن مع نمو المشروع وزيادة المستخدمين، بدأت المشاكل في الظهور.

طريقة التطوير:

  • وسائل التحسين: لا شيء، تطوير مباشر بدون تفكير في الأداء
  • أدوات المراقبة: لا شيء، الحكم على السرعة بالشعور
  • المؤشرات الأساسية: لا شيء

خصائص هذه المرحلة:

  • المميزات: تطوير سريع، لا تكلفة تعلم إضافية
  • العيوب: تجربة مستخدم سيئة، غير قابل للاستخدام عند بطء الشبكة
الاطلاع على المشاكل في ذلك الوقت

المشاكل المحددة التي واجهتهم:

  1. الصور كبيرة جدًا: قام مدير المنتج برفع صورة Banner للصفحة الرئيسية بحجم 5MB، مستخدمو الشبكة المحمولة يستغرقون دقيقة كاملة لفتح الصفحة
  2. لا يوجد ضغط: ملفات CSS وJS غير مضغوطة تمامًا، حجمها 3 أضعاف الحجم بعد الضغط
  3. لا يوجد تخزين مؤقت: كل زيارة تتطلب تنزيل جميع الموارد من جديد، حتى المستخدمون القدامى يضطرون للانتظار
  4. تحميل متزامن: جميع ملفات JS في <head> ويتم تحميلها بشكل متزامن، مما يحظر عرض الصفحة

ملاحظات المستخدمين:

  • "لماذا موقعكم لا يفتح؟"
  • "الصور لا تظهر لفترة طويلة، فقط فراغ"
  • "النقر على الأزرار لا يستجيب، هل الموقع معطل؟"

الحل المؤقت في ذلك الوقت:

html
<!-- استخدام قناع loading "لخداع" المستخدم -->
<div id="loading">جاري التحميل...</div>
<script>
  // إزالة القناع فقط بعد اكتمال تحميل الصفحة
  window.onload = function() {
    document.getElementById('loading').style.display = 'none'
  }
</script>

هذا "خداع للنفس" تمامًا — الصفحة ما زالت بطيئة جدًا، لكن المستخدم لا يراها فقط.

3.3 المرحلة الثانية: التحسين اليدوي — بداية الوعي

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

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

طريقة التطوير:

  • وسائل التحسين: ضغط الصور يدويًا، دمج ملفات CSS/JS، تقليل طلبات HTTP
  • أدوات المراقبة: لوحة Network في المتصفح، سجلات توقيت بسيطة
  • المؤشرات الأساسية: وقت تحميل الصفحة (يتم قياسه يدويًا بساعة توقيت)

خصائص هذه المرحلة:

  • المميزات: تحسن ملحوظ، توقف المستخدمون عن الشكاوى الكثيرة
  • العيوب: التحسين غير منهجي، سهل التراجع، نقص المؤشرات الكمية
الاطلاع على الممارسات المحددة للتحسين اليدوي

وسائل التحسين اليدوي:

  1. ضغط الصور يدويًا:

    • استخدام Photoshop "لحفظ كل صورة بصيغة الويب" يدويًا
    • تحويل PNG إلى JPEG (ضغط مع فقدان، لكن الحجم أصغر بكثير)
    • تصغير أبعاد الصورة (مثل تصغير صورة بعرض 2000px إلى 800px)
  2. دمج الملفات يدويًا:

    html
    <!-- قبل التحسين: 10 ملفات JS = 10 طلبات -->
    <script src="utils.js"></script>
    <script src="api.js"></script>
    <script src="component-a.js"></script>
    <script src="component-b.js"></script>
    ...(6 ملفات أخرى)
    
    <!-- بعد التحسين: ملف JS واحد مدمج = طلب واحد -->
    <script src="all.js"></script>
  3. نقل CSS/JS إلى أسفل الصفحة:

    html
    <body>
      <!-- محتوى الصفحة -->
      <h1>مرحبًا بك</h1>
    
      <!-- تحسين: وضع CSS/JS في النهاية -->
      <link rel="stylesheet" href="style.css">
      <script src="app.js"></script>
    </body>

التحسينات التي تحققت:

  • انخفض حجم الصور من 5MB إلى 500KB (انخفاض بنسبة 90%)
  • انخفض عدد طلبات HTTP من 30 إلى 5
  • انخفض وقت تحميل الصفحة من 30 ثانية إلى 8 ثوانٍ

نقاط الألم الجديدة:

  1. حجم العمل اليدوي كبير: كل تحديث يتطلب ضغط الصور ودمج الملفات يدويًا
  2. سهولة النسيان: الموظفون الجدد لا يعرفون ضرورة التحسين، ويرفعون الصور الأصلية مباشرة
  3. نقص القياس الكمي: يعرفون فقط أنه "أسرع قليلاً"، لكن لا يعرفون بالضبط كم أصبح أسرع

3.4 المرحلة الثالثة: التحسين المنهجي — استخدام الأدوات والبيانات

ظلت مشاكل المرحلة الثانية (حجم العمل اليدوي الكبير، نقص القياس الكمي) تؤرق الفريق لفترة طويلة. حتى اكتشف الفريق لاحقًا أدوات احترافية مثل Lighthouse ولوحة Performance، ودخلوا عصر التحسين المنهجي.

جوهر هذه المرحلة هو التحسين القائم على البيانات — تشخيص المشكلات باستخدام الأدوات أولاً، وإيجاد عنق الزجاجة في الأداء، ثم التحسين بشكل هادف.

طريقة التطوير:

  • وسائل التحسين: تقسيم الكود، التحميل الكسول، القوائم الافتراضية، ضغط الصور التلقائي
  • أدوات المراقبة: Lighthouse، لوحة Chrome Performance، WebPageTest
  • المؤشرات الأساسية: FCP (وقت الشاشة الأولى)، LCP (رسم أكبر محتوى)، TBT (إجمالي وقت الحظر)
الممارسات المحددة للتحسين المنهجي

استخدام Lighthouse لتشخيص المشكلات:

Lighthouse هي أداة اختبار أداء تلقائية طورتها Google، يمكنها تقديم تقرير أداء شامل واقتراحات للتحسين.

bash
# استخدام Lighthouse لاختبار صفحة الويب
lighthouse https://www.example.com --view

سيقدم Lighthouse:

  • تقييم الأداء (0-100 نقطة)
  • المؤشرات الأساسية (FCP، LCP، CLS، TBT، INP)
  • اقتراحات التحسين (مثل "تفعيل ضغط النص"، "إزالة JavaScript غير المستخدم")

شرح المؤشرات الرئيسية:

المؤشرالاسم الكاملالمعنىالقيمة المثالية
FCPFirst Contentful Paintوقت رسم أول محتوى (الوقت الذي يرى فيه المستخدم أول جزء من المحتوى)<1.8s
LCPLargest Contentful Paintوقت رسم أكبر محتوى (الوقت الذي يكتمل فيه تحميل المحتوى الرئيسي)<2.5s
TBTTotal Blocking Timeإجمالي وقت الحظر (إجمالي الوقت الذي يكون فيه الخيط الرئيسي محظورًا)<200ms
CLSCumulative Layout Shiftالتحول التراكمي للتخطيط (مدى قفز عناصر الصفحة)<0.1

خصائص هذه المرحلة:

  • المميزات: تحسين هادف، نتائج جيدة، مع مؤشرات كمية
  • العيوب: تحتاج إلى تعلم الأدوات والمؤشرات، مع عتبة معينة
الاطلاع على التقنيات المحددة للتحسين المنهجي

1. تقسيم الكود (Code Splitting):

تقسيم الملفات الكبيرة إلى ملفات صغيرة، وتحميلها حسب الحاجة. مثلًا، عندما يزور المستخدم الصفحة الرئيسية، يتم تحميل كود الصفحة الرئيسية فقط، وعند النقر على "من نحن"، يتم تحميل كود صفحة "من نحن".

js
// قبل التحسين: كل الكود في ملف واحد، تحميل مرة واحدة
import About from './views/About.vue'
import Contact from './views/Contact.vue'
// ... 10 صفحات أخرى

// بعد التحسين: تحميل كسول، يتم التحميل عند الزيارة
const About = () => import('./views/About.vue')
const Contact = () => import('./views/Contact.vue')

النتيجة: انخفضت كمية الكود المحمل في الصفحة الرئيسية بنسبة 70%، وانخفض وقت الشاشة الأولى من 5 ثوانٍ إلى 1.5 ثانية.

2. التحميل الكسول للصور (Lazy Loading):

تحميل الصور التي يراها المستخدم فقط، وعند التمرير إلى المنطقة المرئية يتم تحميل الصور الأخرى.

html
<!-- المتصفحات الحديثة تدعم التحميل الكسول الأصلي -->
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy" />

النتيجة: انخفض عدد الصور المحملة في الصفحة الرئيسية من 20 إلى 3، مما وفر 80% من النطاق الترددي.

3. القوائم الافتراضية (Virtual Scrolling):

إذا كنت تريد عرض 10,000 سجل بيانات، لا تنشئ فعليًا 10,000 عقدة DOM، بل اعرض فقط 20 عنصرًا في المنطقة المرئية، واستبدلها ديناميكيًا عند التمرير.

vue
<!-- استخدام مكون vue-virtual-scroller -->
<RecycleScroller
  :items="items"
  :item-size="50"
  key-field="id"
>
  <template #default="{ item }">
    <div>{{ item.name }}</div>
  </template>
</RecycleScroller>

النتيجة: تحولت 10,000 سجل بيانات من "توقف تام" إلى "تمرير سلس"، وانخفض استخدام الذاكرة بنسبة 95%.

3.5 المرحلة الرابعة: التحسين المستمر — دمج الأداء في سير عمل التطوير

عندما نضجت الأدوات والأساليب، بدأ الفريق في التركيز على أسئلة أعمق: كيف نمنع تراجع الأداء؟ كيف نجعل الأداء جزءًا من سير عمل التطوير؟

جوهر هذه المرحلة هو إنشاء نظام مراقبة وميزانية للأداء — ليس التحسين بعد الإطلاق، بل منع مشاكل الأداء في مرحلة التطوير.

طريقة التطوير:

  • وسائل التحسين: ميزانية الأداء (Performance Budget)، Lighthouse CI، مراقبة المستخدم الحقيقي (RUM)
  • أدوات المراقبة: Lighthouse CI، WebPageTest API، Google Analytics
  • المؤشرات الأساسية: INP (تأخير التفاعل)، CLS (تحول التخطيط)، مراقبة شاملة
الممارسات المحددة للتحسين المستمر

1. وضع ميزانية الأداء:

وضع قيود في إعدادات الحزمة، والتنبيه عند تجاوزها، لمنع "إدخال ملفات كبيرة عن غير قصد".

js
// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        // تقييد حجم الملف الواحد بما لا يتجاوز 200KB
        chunkFileNames: 'js/[name]-[hash].js',
      }
    },
    // تحذير عند تجاوز 200KB
    chunkSizeWarningLimit: 200
  }
})

2. Lighthouse CI:

عند كل إرسال للكود، يتم تشغيل اختبار Lighthouse تلقائيًا، وإذا انخفضت درجة الأداء، يتم منع الدمج.

yaml
# .github/workflows/lighthouse.yml
name: Lighthouse CI
on: [pull_request]
jobs:
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v9
        with:
          urls: |
            https://staging.example.com
          budgetPath: ./budget.json

3. مراقبة المستخدم الحقيقي (RUM):

جمع بيانات الأداء من متصفحات المستخدمين الحقيقيين، بدلاً من الاختبار في بيئة التطوير فقط.

js
// إرسال بيانات الأداء إلى الخادم
const perfData = performance.getEntriesByType('navigation')[0]
const lcp = performance.getEntriesByType('largest-contentful-paint')[0]

fetch('/api/perf', {
  method: 'POST',
  body: JSON.stringify({
    fcp: perfData.loadEventEnd - perfData.fetchStart,
    lcp: lcp.renderTime || lcp.loadTime,
    url: window.location.href
  })
})

النتيجة:

  • يمكن اكتشاف تراجع الأداء في الوقت المناسب (مثلًا، إرسال معين تسبب في زيادة LCP من ثانيتين إلى 5 ثوانٍ)
  • يمكن فهم تجربة المستخدمين الحقيقيين (وليس "الحالة المثالية" في بيئة التطوير)
  • يمكن استهداف تحسين أبطأ 10% من المستخدمين

ماذا ستفعل في هذه المرحلة؟

  1. ميزانية الأداء: تقييد حجم الملفات وعدد الطلبات، والتنبيه عند التجاوز
  2. فحص CI/CD: اختبار تلقائي للأداء عند كل إرسال للكود، ومنع الدمج عند التراجع
  3. مراقبة المستخدم الحقيقي: جمع بيانات الأداء من المستخدمين الحقيقيين، وتحسين مستمر
  4. تقارير أداء دورية: إنشاء تقارير أداء أسبوعية/شهرية، وتتبع الاتجاهات

4. عنق الزجاجة الشائع في الأداء والحلول

بعد الحديث عن الكثير من النظريات، لننظر إلى مشاكل الأداء الأكثر شيوعًا في التطوير الفعلي، وكيفية حلها.

4.1 تحميل الصور بطيء

مظهر المشكلة: الصور لا تظهر لفترة طويلة، أو الصفحة تقفز أثناء عملية التحميل.

الأسباب:

  • حجم الصور كبير جدًا (صور أصلية عالية الدقة)
  • أبعاد الصور كبيرة جدًا (صورة بعرض 2000px تُعرض بحجم 200px)
  • لا يوجد تحميل كسول (تحميل جميع الصور دفعة واحدة)

الحلول:

  1. استخدام صيغ الصور الحديثة (WebP، AVIF):
html
<!-- حديث: صيغة WebP، حجم أصغر بنسبة 30-70% -->
<picture>
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="صورة">
</picture>
  1. الصور المتجاوبة (تحميل أحجام مختلفة حسب حجم الجهاز):
html
<!-- الأجهزة الصغيرة تحمل صورًا صغيرة، والأجهزة الكبيرة تحمل صورًا كبيرة -->
<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w,
          image-800.jpg 800w,
          image-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px,
         (max-width: 1200px) 800px,
         1200px"
  alt="صورة متجاوبة">
  1. التحميل الكسول (التحميل عند تمرير المستخدم):
html
<!-- حديث: تحميل كسول أصلي -->
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy" />

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

Image Format Comparison: Size and Quality Tradeoffs
Compare size and quality across image formats.
JPEG
Classic
🖼️
500 KB
File size500 KB
Compression70%
Quality
Browser support100%
Use case
Photos and complex images
PNG
Lossless
🖼️
1.2 MB
File size1.2 MB
Compression40%
Quality
Browser support100%
Use case
Transparent images and icons
WebP
🖼️
250 KB
File size250 KB
Compression85%
Quality
Browser support95%
Use case
Most scenarios
AVIF
Newest
🖼️
180 KB
File size180 KB
Compression90%
Quality
Browser support75%
Use case
Maximum performance

Detailed Comparison

FormatSizeQualityTransparencyAnimationRecommendation
JPEGMediumGood
★★★★☆
PNGLargePerfect
★★★★★
WebPSmallExcellent
★★★★★
AVIFSmallestOutstanding
★★★★★
💡

Optimization Tips

  • Prefer WebP to reduce size by 30-50%.
  • Provide JPEG/PNG fallbacks for older browsers.
  • Use the <picture> element for automatic fallback.
  • Use JPEG for photos and PNG or SVG for icons.
🔧

Recommended Tools

  • Squoosh: open-source image compression from Google.
  • ImageOptim: image optimization tool for macOS.
  • TinyPNG: online smart compression with WebP support.
  • Sharp: Node.js image processing library for automation.

4.2 بطء تحميل الشاشة الأولى

مظهر المشكلة: يفتح المستخدم صفحة الويب، وتكون الشاشة بيضاء لفترة طويلة.

الأسباب:

  • تحميل الكثير من الكود غير الضروري
  • مسار العرض الحرج محظور
  • لم يتم تقسيم الكود

الحلول:

  1. تقسيم الكود (Code Splitting):
js
// تحميل كسول للتوجيه: التحميل عند الزيارة فقط
const routes = [
  {
    path: '/about',
    component: () => import('./views/About.vue')  // التحميل فقط عند زيارة /about
  }
]
  1. التحميل المسبق للموارد الحرجة (Preload):
html
<!-- إخبار المتصفح مسبقًا: هذه الموارد مهمة، حملها بأولوية -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="hero-image.jpg" as="image">
  1. تضمين CSS الحرجة:
html
<!-- تضمين CSS المطلوبة للشاشة الأولى مباشرة في HTML -->
<style>
  /* أنماط الشاشة الأولى الحرجة */
  .hero { background: #000; color: #fff; }
</style>

4.3 توقف التمرير

مظهر المشكلة: الصفحة متقطعة عند التمرير، غير سلسة.

الأسباب:

  • عرض عدد كبير جدًا من عقد DOM (مثل 10,000 سجل بيانات)
  • حسابات معقدة في مستمعي أحداث التمرير
  • تشغيل متكرر لحسابات التخطيط

الحلول:

  1. القوائم الافتراضية (Virtual Scrolling):
vue
<!-- عرض محتوى المنطقة المرئية فقط -->
<RecycleScroller
  :items="10000"
  :item-size="50"
>
  <template #default="{ item }">
    <div>{{ item.name }}</div>
  </template>
</RecycleScroller>

👇 جرب بنفسك: العرض التوضيحي التالي يقارن بين أداء القائمة العادية والقائمة الافتراضية:

📜Virtual ScrollingRender only the list items visible in the viewport.
Total items
10,000
Actually rendered
8
Memory saved
~99.9%
1Item #1 - virtual scrolling list item content
2Item #2 - virtual scrolling list item content
3Item #3 - virtual scrolling list item content
4Item #4 - virtual scrolling list item content
5Item #5 - virtual scrolling list item content
6Item #6 - virtual scrolling list item content
7Item #7 - virtual scrolling list item content
8Item #8 - virtual scrolling list item content
💡How it works: Instead of rendering all 10000 items, it renders only the visible viewport items plus a small buffer. On scroll, it calculates which items should appear and uses absolute positioning to create the illusion of a full list. Performance improves from O(n) to O(1).
  1. التحكم في تدفق أحداث التمرير (Throttle):
js
// تقييد تكرار تشغيل أحداث التمرير (مرة واحدة كل 100ms كحد أقصى)
const throttledScroll = throttle(() => {
  updatePosition()
}, 100)

window.addEventListener('scroll', throttledScroll)
  1. استخدام CSS will-change:
css
/* إخبار المتصفح مسبقًا: هذا العنصر سيتغير، يرجى الاستعداد */
.scroll-container {
  will-change: transform;
}

4.4 بطء استجابة النقر

مظهر المشكلة: بعد النقر على الزر، يستغرق عدة ثوانٍ للاستجابة.

الأسباب:

  • حسابات معقدة في معالج حدث النقر (تحظر الخيط الرئيسي)
  • عدم استخدام منع الاهتزاز (نقرات متعددة سريعة من المستخدم تشغل حسابات متعددة)

الحلول:

  1. منع اهتزاز حدث النقر (Debounce):
js
// التنفيذ فقط بعد توقف المستخدم عن النقر لمدة 300ms
const debouncedClick = debounce(() => {
  submitForm()
}, 300)

button.addEventListener('click', debouncedClick)
  1. استخدام Web Worker (نقل الحسابات إلى خيط خلفي):
js
// الخيط الرئيسي
const worker = new Worker('calculator.js')
button.addEventListener('click', () => {
  worker.postMessage({ data: largeData })
})

worker.onmessage = (e) => {
  // اكتمل الحساب، عرض النتيجة
  showResult(e.data.result)
}

// calculator.js (خيط Worker)
self.onmessage = (e) => {
  const result = heavyCalculation(e.data.data)
  self.postMessage({ result })
}

5. أدوات مراقبة الأداء

تحسين الأداء ليس عملاً لمرة واحدة، بل يحتاج إلى مراقبة مستمرة. فيما يلي الأدوات الشائعة.

5.1 أدوات مطور المتصفح

Chrome DevTools هي أكثر أدوات تحليل الأداء استخدامًا:

  • لوحة Network: عرض حالة تحميل الموارد
  • لوحة Performance: تحليل أداء وقت التشغيل (FPS، نشاط الخيط الرئيسي)
  • Lighthouse: إنشاء تقرير أداء بنقرة واحدة

كيفية استخدام لوحة Performance

  1. افتح Chrome DevTools (F12)
  2. انتقل إلى لوحة Performance
  3. انقر على زر "Record"
  4. تفاعل مع صفحة الويب (التمرير، النقر، إلخ)
  5. انقر على "Stop" لإيقاف التسجيل
  6. حلل النتائج: انظر إلى FPS (معدل الإطارات)، نشاط الخيط الرئيسي، المهام الطويلة، إلخ

5.2 Lighthouse

Lighthouse هي أداة اختبار أداء تلقائية طورتها Google:

bash
# الاستخدام من سطر الأوامر
lighthouse https://www.example.com --view

# أو الاستخدام من Chrome DevTools
# افتح DevTools → Lighthouse → انقر على "Analyze page load"

سيقدم Lighthouse:

  • تقييم الأداء (0-100 نقطة)
  • المؤشرات الأساسية (FCP، LCP، CLS، TBT، INP)
  • اقتراحات التحسين (مرتبة حسب التأثير)

5.3 WebPageTest

WebPageTest هي أداة اختبار أداء عبر الإنترنت، يمكنها الاختبار من مواقع وأجهزة متعددة:

bash
# زيارة https://www.webpagetest.org
# أدخل عنوان URL، اختر موقع الاختبار والجهاز، انقر على "Start Test"

سيقدم WebPageTest:

  • مخطط الشلال (Waterfall): الخط الزمني لتحميل كل مورد
  • مقارنة فيديو: فيديو لعملية التحميل قبل التحسين وبعده
  • اقتراحات التحسين

6. قائمة تحسين الأداء

فيما يلي قائمة عملية لتحسين الأداء، يمكنك تحسين صفحتك بهذا الترتيب:

6.1 تحسين التحميل

  • ضغط الصور: استخدام صيغة WebP، جودة الضغط 80-85%
  • الصور المتجاوبة: تحميل أحجام مختلفة من الصور حسب حجم الجهاز
  • التحميل الكسول: تحميل كسول للصور والمكونات، تحميل المحتوى المرئي فقط
  • تقسيم الكود: تقسيم الكود حسب المسار، تحميل حسب الحاجة
  • ضغط الكود: تفعيل ضغط Gzip/Brotli
  • استخدام CDN: وضع الموارد الثابتة على CDN، لتسريع التنزيل
  • التحميل المسبق للموارد الحرجة: استخدام <link rel="preload">

6.2 تحسين العرض

  • تقليل إعادة التخطيط وإعادة الرسم: استخدام transform و opacity بدلاً من top و width
  • القوائم الافتراضية: استخدام التمرير الافتراضي عند وجود بيانات كبيرة
  • رسوم CSS المتحركة: تفضيل رسوم CSS المتحركة بدلاً من رسوم JavaScript المتحركة
  • تحسين مسار العرض الحرج: تضمين CSS الحرجة، تأخير تحميل CSS غير الحرجة
  • تجنب @import: @import يحظر العرض، استخدم <link> بدلاً منه

6.3 تحسين التفاعل

  • منع الاهتزاز والتحكم في التدفق: استخدام منع الاهتزاز/التحكم في التدفق لأحداث التمرير والإدخال وresize
  • Web Worker: نقل الحسابات المعقدة إلى خيط خلفي
  • تقسيم الوقت: تقسيم المهام الكبيرة إلى مهام صغيرة، تجنب المهام الطويلة
  • تجنب التخطيط المتزامن: لا تقرأ خصائص التخطيط (مثل offsetHeight) داخل الحلقات

6.4 تحسين التخزين المؤقت

  • التخزين المؤقت HTTP: تكوين Cache-Control و ETag
  • Service Worker: تخزين الموارد الثابتة مؤقتًا، لتحقيق الوصول دون اتصال
  • LocalStorage: تخزين بيانات API مؤقتًا، لتقليل الطلبات
  • التخزين المؤقت في الذاكرة: استخدام Map/Object لتخزين نتائج الحسابات مؤقتًا

6.5 تحسين المراقبة

  • Lighthouse CI: اختبار تلقائي للأداء عند كل إرسال للكود
  • مراقبة المستخدم الحقيقي: جمع بيانات الأداء من المستخدمين الحقيقيين
  • ميزانية الأداء: وضع حدود لحجم الملفات، والتنبيه عند التجاوز
  • تقارير أداء دورية: إنشاء تقارير اتجاهات الأداء أسبوعيًا/شهريًا

7. الخلاصة

لنراجع المفاهيم الأساسية لتحسين أداء الواجهة الأمامية باستخدام جدول:

المفهومشرح بكلمة واحدةالمشكلة التي يحلهاالوسائل الشائعة
تحسين التحميلجعل تنزيل الموارد أسرعبطء الشاشة الأولى، وقت انتظار طويلضغط الصور، CDN، تقسيم الكود، التحميل الكسول
تحسين العرضجعل "رسم" الصفحة أسرعتوقف التمرير، بطء النقرالقوائم الافتراضية، تقليل إعادة التخطيط وإعادة الرسم، رسوم CSS المتحركة
تحسين التفاعلجعل الاستجابة أسرععدم استجابة النقر، توقف العملياتمنع الاهتزاز والتحكم في التدفق، Web Worker، تقسيم الوقت
تحسين التخزين المؤقتتجنب التنزيل المتكرربطء الزيارات المتكررةالتخزين المؤقت HTTP، Service Worker، LocalStorage
تحسين المراقبةاكتشاف المشكلات باستمرارتراجع الأداءLighthouse، RUM، ميزانية الأداء

كلمة أخيرة

تحسين الأداء موضوع في تطور مستمر، الأدوات تتغير، لكن المفهوم الأساسي لا يتغير: التفكير من منظور المستخدم، جعل وقت الانتظار أقصر، وجعل العمليات أكثر سلاسة.

بفهم هذه المبادئ الأساسية، ستتمكن من التأقلم بسرعة مع أي تقنيات جديدة، مهما تغيرت.

نأمل أن يساعدك هذا المقال في بناء فهم شامل لتحسين أداء الواجهة الأمامية. عندما تواجه مشاكل الأداء في مشاريعك الفعلية، ستعرف من أين تبدأ، وكيف تحدد المشكلة، وكيف تحلها.