واجهة برمجة تطبيقات IntersectionObserver وتحميل الصور البطيئة

يعد استخدام التحميل البطيء للصور لتحسين أداء مشاريع الويب أحد أساليب التحسين الشائعة. الشيء هو أن الصور هي موارد "ثقيلة" مزدحمة بالمواقع الحديثة. لقد نشرنا بالفعل شيئًا عن هذا. هنا يمكنك أن تقرأ عن ما أعطاه التحميل البطيء لموقع Walmart ، وتعلم كيفية استخدام IntersectionObserver في مشاريع React. هنا مقال عن تحسين المواقع الثابتة. فيما يلي مواد حديثة حول تطبيق التحميل البطيء باستخدام أدوات المتصفح.



نلفت انتباهك اليوم إلى ترجمة لمقال وصف فيه استخدام واجهة برمجة تطبيقات IntersectionObserver باستخدام صفحة ويب بسيطة كمثال. هذه المادة مخصصة للمبرمجين المبتدئين.

ما هو تحميل الصور كسول؟


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

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

  1. وقت التفاعل الأول. هذا هو الوقت الذي يحتاج فيه تطبيق الويب إلى التحميل وإدخال الواجهة في حالة مناسبة للمستخدم للعمل معها. التحميل الكسول (علاوة على ذلك ، لا يتعلق بالصور فقط) يعمل على تحسين وقت استجابة التطبيقات بفضل تقنية فصل الشفرة وتحميل ما تحتاج إليه صفحة معينة فقط أو ما تحتاجه في وقت محدد.
  2. استهلاك الموارد. البشر كائنات غير صبور. إذا كان موقع الويب يحتاج إلى تحميل أكثر من 3 ثوانٍ ، فإن 70٪ من المستخدمين يتركون هذا الموقع. يجب ألا يتم تحميل تطبيقات الويب لفترة طويلة. يتيح لك التحميل البطيء تقليل مقدار الموارد اللازمة لصفحات العمل. قد يعني هذا ، على سبيل المثال ، أن رمز مشروع معين مقسم إلى أجزاء يتم تحميلها فقط على تلك الصفحات التي تحتاج إليها. نتيجة لذلك ، يزداد أداء الموقع وينخفض ​​استهلاك موارد النظام.

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

فيما يلي بعض المزايا التي يوفرها التحميل البطيء لمشاريع الويب:

  • يتم تحميل الصفحات بشكل أسرع وتشغيلها.
  • عند التحميل الأولي للصفحات ، يتعين عليك نقل بيانات أقل ومعالجتها.

كسول تحميل الصور باستخدام API IntersectionObserver


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

النظر في مثال.


الصفحة ومساحتها المرئية

نلقي نظرة على الشكل السابق. هنا يمكنك رؤية المتصفح وصفحة الويب المحملة فيه. الصور #IMG_1 و #IMG_2 في نطاق الصفحة. هذا يعني أنها مرئية للمستخدم وتكون ضمن حدود منطقة نافذة المتصفح التي يتم عرضها على الشاشة.

لا يمكن اعتبار ترتيب العمل هذا مع الصفحة مثاليًا عندما يتم تحميل الصور #IMG_1 و #IMG_2 و #IMG_3 و #IMG_4 . فقط #IMG_1 و #IMG_2 مرئيان #IMG_2 ، و #IMG_3 و #IMG_4 مخفيان عنه. إذا قمت بتحميل الصورتين الأولى والثانية أثناء تحميل الصفحة ، لكنك لم تقم بتنزيل الصورتين الثالثة والرابعة ، فقد يكون لذلك تأثير إيجابي على أداء الموقع. وهي نتحدث عن ما يلي. عندما يقوم المستخدم بالتمرير في الصفحة بحيث تصبح الصورة الثالثة مرئية - يتم تحميلها. إذا استمر التمرير وأصبحت الصورة الرابعة مرئية ، فسيتم تحميلها أيضًا.


التمرير صفحة وتحميل الصور

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

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

 <img class="lzy_img" src="lazy_img.jpg" data-src="real_img.jpg" /> 

يتيح لك الفصل تحديد عنصر كصورة سيتم تطبيق التحميل البطيء عليها. تتيح لك سمة src عرض صورة عنصر نائب قبل عرض الصورة الفعلية. data-src بتخزين عنوان الصورة الحقيقية ، والتي سيتم تحميلها عندما يدخل العنصر في المنطقة المرئية من الصفحة.

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

أولاً ، قم بإنشاء مثيل لـ IntersectionObserver :

 const imageObserver = new IntersectionObserver(...); 

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

 const imageObserver = new IntersectionObserver((entries, imgObserver) => {   entries.forEach((entry) => {       //...   }) }); 

يتحقق رمز الوظيفة لمعرفة ما إذا كانت الصور الممثلة في entries صفيف entries تتقاطع مع إطار العرض. إذا كانت هذه هي الحالة ، فإن السمة src للصورة المقابلة تسجل ما كان في السمة data-src الخاصة data-src .

 const imageObserver = new IntersectionObserver((entries, imgObserver) => {   entries.forEach((entry) => {       if(entry.isIntersecting) {           const lazyImage = entry.target           lazyImage.src = lazyImage.dataset.src       }   }) }); 

نحن نتحقق هنا ، باستخدام الشرط if(entry.isIntersecting) {...} ، ما إذا كان العنصر يعبر منطقة عرض المتصفح. إذا كان الأمر كذلك ، فإننا lazyImage عنصر img في ثابت lazyImage . ثم نكتب في السمة src ما كان في السمة data-src . بفضل هذا ، فإن الصورة التي يتم تخزين عنوانها في data-src يتم تحميلها وعرضها. في المتصفح ، يبدو أن استبدال صورة العنصر النائب ، lazy_img.jpg ، مع صورة حقيقية.

نحتاج الآن إلى استخدام طريقة .observe() لمثيل IntersectionObserver بنا من أجل البدء في مراقبة العناصر التي تهمنا:

 imageObserver.observe(document.querySelectorAll('img.lzy_img')); 

نحن هنا نختار جميع عناصر img مع فئة lzy_img document.querySelectorAll('img.lzy_img') باستخدام الأمر document.querySelectorAll('img.lzy_img') .observe() طريقة .observe() . بعد تلقي قائمة من العناصر ، يبدأ عملية مراقبة هذه العناصر.

لاختبار هذا المثال ، نبدأ بتهيئة مشروع Node.js:

 mkdir lzy_img cd lzy_img npm init -y 

قم الآن بإنشاء ملف lzy_img في المجلد lzy_img :

 touch index.html 

أضف الكود التالي إليها:

 <html> <title>Lazy Load Images</title> <body>   <div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_1.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_2.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_3.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_4.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_5.jpg" />           <hr />       </div>   </div>   <script>       document.addEventListener("DOMContentLoaded", function() {           const imageObserver = new IntersectionObserver((entries, imgObserver) => {               entries.forEach((entry) => {                   if (entry.isIntersecting) {                       const lazyImage = entry.target                       console.log("lazy loading ", lazyImage)                       lazyImage.src = lazyImage.dataset.src                   }               })           });           const arr = document.querySelectorAll('img.lzy_img')           arr.forEach((v) => {               imageObserver.observe(v);           })       })   </script> </body> </html> 

قد تلاحظ أن هناك 5 صور موصوفة هنا ، حيث يتم عرض العنصر النائب lazy_img.jpg عند التحميل. تحتوي سمة data-src لكل منهما على معلومات حول الصور الحقيقية. فيما يلي قائمة بأسماء الصور المستخدمة في المشروع:

 lazy_img.jpg img_1.jpg img_2.jpg img_3.jpg img_4.jpg img_5.jpg 

تحتاج إلى إنشاء كل هذه الصور بنفسك عن طريق إحضار مجلد المشروع إلى العرض الموضح في الشكل التالي.


مجلد المشروع

في حالتي ، lazy_img.jpg إعداد ملف lazy_img.jpg باستخدام Windows Paint ، وتم التقاط الصور الحقيقية ( img_*.jpg Jpg ) من pixabay.com .

لاحظ أن رد الاتصال المستخدم لإنشاء مثيل IntersectionObserver لديه استدعاء console.log() . سيتيح لنا ذلك معرفة كيفية إجراء عمليات لتحميل صور مختلفة.

الآن ، لخدمة index.html ، نستخدم حزمة http-server :

 npm i http-server 

أضف خاصية start إلى قسم scripts لملف package.json :

 "scripts": {   "start": "http-server ./" } 

بعد ذلك ، قم بتنفيذ الأمر npm run start في الجهاز.

الآن افتح المتصفح وانتقل إلى العنوان 127.0.0.1:8080 . صفحة index.html بنا في البداية ستبدو بالشكل التالي.


صفحة بدون صور حقيقية

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


متصفح تحميل الصورة الأولى

صور أخرى لم يتم تحميلها بعد. لم يصلوا بعد إلى منطقة المشاهدة.

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


تحميلات متعددة من نفس الصورة

هذا ليس على الإطلاق ما نحتاجه. وهذا يؤدي إلى إهدار موارد النظام بشكل غير ضروري وتقليل أداء المشروع.

لحل هذه المشكلة ، نحتاج إلى إزالة عنصر img ، الصورة الحقيقية التي تم تحميلها بالفعل ، من قائمة العناصر التي IntersectionObserver مثيل IntersectionObserver بنا. نحتاج أيضًا إلى إزالة الفئة lzy_img من هذا العنصر. إليك ما يبدو عليه في رمز وظيفة رد الاتصال الذي تم تعديله:

 <script>   document.addEventListener("DOMContentLoaded", function() {       const imageObserver = new IntersectionObserver((entries, imgObserver) => {           entries.forEach((entry) => {               if (entry.isIntersecting) {                   const lazyImage = entry.target                   console.log("lazy loading ", lazyImage)                   lazyImage.src = lazyImage.dataset.src                   lazyImage.classList.remove("lzy_img");                   imgObserver.unobserve(lazyImage);               }           })       });       const arr = document.querySelectorAll('img.lzy_img')       arr.forEach((v) => {           imageObserver.observe(v);       })   }) </script> 

بعد تحميل الصورة الحقيقية لعنصر img المقابل ، يتم lzy_img الفئة lzy_img ويتم استبعاد العنصر من قائمة العناصر التي يراقبها IntersectionObserver .

هنا هو رمز عينة:

 <html> <title>Lazy Load Images</title> <body>   <div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_1.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_2.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_3.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_4.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_5.jpg" />           <hr />       </div>   </div>   <script>       document.addEventListener("DOMContentLoaded", function() {           const imageObserver = new IntersectionObserver((entries, imgObserver) => {               entries.forEach((entry) => {                   if (entry.isIntersecting) {                       const lazyImage = entry.target                       console.log("lazy loading ", lazyImage)                       lazyImage.src = lazyImage.dataset.src                       lazyImage.classList.remove("lzy_img");                       imgObserver.unobserve(lazyImage);                   }               })           });           const arr = document.querySelectorAll('img.lzy_img')           arr.forEach((v) => {               imageObserver.observe(v);           })       })   </script> </body> </html> 

النتائج


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

أعزائي القراء! هل لديك أي أمثلة لتحسين أداء موقع الويب بعد تطبيق نظام تحميل الصور البطيء؟

Source: https://habr.com/ru/post/ar453586/


All Articles