تحسين الأداء باستخدام JavaScript

الدرس الثاني والعشرون: تحسين الأداء باستخدام JavaScript

عند بناء تطبيقات الويب، يعتبر تحسين الأداء أمرًا بالغ الأهمية لضمان تجربة مستخدم سلسة وسريعة. في هذا الدرس، سنتناول بعض التقنيات الأساسية لتحسين الأداء في JavaScript مثل Debouncing و Throttling، بالإضافة إلى تقنيات Lazy Loading و Code Splitting لتحميل البيانات والمحتويات بشكل ديناميكي وفعال.

1. Debouncing و Throttling لتحسين الأداء

Debouncing

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

مثال على Debouncing:

نفترض أن لدينا وظيفة للبحث في قاعدة بيانات أثناء الكتابة في مربع نص:

let timer;
function search(query) {
  clearTimeout(timer);  // إيقاف أي عملية بحث سابقة
  timer = setTimeout(() => {
    console.log("Searching for:", query);
    // استدعاء عملية البحث هنا
  }, 300); // الانتظار لمدة 300 مللي ثانية بعد آخر كتابة
}

// استخدام الدالة
document.getElementById('searchBox').addEventListener('input', (event) => {
  search(event.target.value);
});

شرح الكود:

  • عند كتابة النص، يتم استدعاء دالة search في كل مرة.
  • باستخدام debounce، نقوم بتأجيل تنفيذ البحث حتى يتوقف المستخدم عن الكتابة لمدة 300 مللي ثانية.
  • إذا كان هناك إدخال جديد قبل انتهاء الوقت المحدد، فإننا نوقف العملية السابقة ونعيد ضبط العداد.

Throttling

تقنية Throttling تحد من عدد مرات تنفيذ الدالة خلال فترة زمنية معينة، بغض النظر عن عدد مرات تفعيل الحدث. تستخدم هذه التقنية بشكل شائع في التعامل مع أحداث مثل التمرير (scrolling) أو تغيير حجم النافذة (resize)، بحيث يمكن أن يتم استدعاء الدالة مرة واحدة فقط خلال فترة زمنية محددة.

مثال على Throttling:

let lastTime = 0;
function throttle(fn, delay) {
  return function() {
    let now = new Date().getTime();
    if (now - lastTime >= delay) {
      lastTime = now;
      fn.apply(this, arguments);
    }
  };
}

// استخدام الدالة throttle لتقليل استدعاء دالة التمرير
window.addEventListener('scroll', throttle(() => {
  console.log("Scrolled!");
}, 200)); // استدعاء الدالة مرة كل 200 مللي ثانية

شرح الكود:

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

2. تقنيات Lazy Loading لتحميل العناصر عند الحاجة

Lazy Loading هي تقنية لتحميل الموارد (مثل الصور أو البيانات) فقط عندما يحتاجها المستخدم، مما يقلل من زمن تحميل الصفحة الأولي ويحسن الأداء بشكل عام. يتم تحميل المحتوى فقط عندما يكون مرئيًا على الشاشة أو عندما يتم طلبه من قبل المستخدم.

مثال على Lazy Loading للصور:

<img data-src="image.jpg" class="lazyload" alt="Lazy Loaded Image">
// استخدام IntersectionObserver لتحميل الصور عند ظهورها في العرض
let lazyImages = document.querySelectorAll('img.lazyload');

let observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src;  // تحميل الصورة
      entry.target.classList.remove('lazyload');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.1 }); // 10% من الصورة يظهر في العرض

lazyImages.forEach(image => {
  observer.observe(image);
});

شرح الكود:

  • باستخدام IntersectionObserver، نراقب العناصر التي تحتوي على فئة lazyload وعندما تظهر في العرض (أي في نافذة العرض)، نقوم بتعيين عنوان الصورة من خاصية data-src إلى خاصية src وبالتالي تحميل الصورة.
  • هذه التقنية تجعل الصفحة تحميل بشكل أسرع لأنها لا تقوم بتحميل الصور إلا عند الحاجة.

3. تقنيات Code Splitting لتقسيم الكود وتحميله بشكل ديناميكي

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

مثال على Code Splitting باستخدام Webpack:

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

// التحميل الديناميكي باستخدام import()
document.getElementById('loadBtn').addEventListener('click', () => {
  import('./module.js')  // تحميل الوحدة عند الحاجة
    .then((module) => {
      module.loadFunction();  // استخدام الوحدة بعد تحميلها
    })
    .catch((error) => {
      console.log('Error loading module:', error);
    });
});

شرح الكود:

  • عند الضغط على الزر، يتم تحميل الوحدة module.js بشكل ديناميكي باستخدام import().
  • هذه الطريقة تتيح تحميل الكود فقط عندما يحتاجه المستخدم بدلاً من تحميله مع الصفحة بالكامل.
  • يمكن تنفيذ هذه التقنية باستخدام أدوات مثل Webpack أو Parcel التي تدعم تقسيم الكود بشكل تلقائي.

الخلاصة

  • Debouncing و Throttling هما تقنيتان مهمتان لتحسين الأداء، خاصة عند التعامل مع أحداث المستخدم المتكررة مثل الكتابة أو التمرير. تساعد هذه التقنيات في تقليل عدد العمليات التي يتم تنفيذها وتساهم في جعل التطبيق أكثر استجابة.
  • Lazy Loading يُحسن أداء الصفحة عن طريق تحميل المحتوى فقط عند الحاجة، مثل تحميل الصور أو البيانات فقط عندما تصبح مرئية أو عندما يطلبها المستخدم.
  • Code Splitting يُمكنك من تقسيم الكود البرمجي وتحميل الأجزاء المطلوبة فقط عند الحاجة، مما يقلل من وقت تحميل الصفحة ويجعل تجربة المستخدم أكثر سلاسة.

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


اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك رد

Scroll to Top