تاريخ النشر: 16 أغسطس 2019، تاريخ آخر تعديل: 2 يوليو 2026
كما هو الحال مع عناصر الصور، قد تحتاج أيضًا إلى تحميل الفيديو بشكل غير متزامن. يتم عادةً تحميل الفيديوهات باستخدام العنصر <video>، ولكن بالنسبة إلى الفيديوهات المستضافة على خدمات أخرى مثل YouTube، قد يتم استخدام <iframe> (في هذه الحالة، يمكنك الاطّلاع على المقالة في التحميل الكسول لإطارات iframe).
تعتمد طريقة تحميل <video> بشكل غير متزامن على حالة الاستخدام، إذ تتوفّر حلول مختلفة.
استخدام السمة loading
بدأت المتصفحات في إتاحة السمة loading على عناصر الوسائط (<video> و<audio>). وعندما تكون هذه السمة متاحة، يعني ذلك أنّه يتم تلقائيًا تحميل الوسائط وأي صورة ملصق بشكل كسول بمجرّد إضافة السمة loading="lazy":
<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
سيؤدي استخدام loading="lazy" إلى منع تحميل الصورة poster نهائيًا إلى أن تصبح في إطار العرض أو بالقرب منه، ثم سيتم استخدام السمة preload لتحديد مقدار video الذي سيتم تحميله. يعني هذا أيضًا أنّه لن يتم تشغيل فيديوهات autoplay تلقائيًا إلا عندما تكون في إطار العرض أو بالقرب منه. تعمل السمة loading="lazy" مع السمات poster وpreload وautoplay، ولا تحلّ محلّ الحاجة إليها.
ستتجاهل المتصفحات التي لا تتوافق مع السمة loading في عناصر الوسائط هذه السمة، ما سيؤدي إلى تحميل الصورة poster على الفور، وتحميل الفيديو استنادًا إلى السمة preload التي سنتناولها لاحقًا.
استخدام السمة preload لتحميل الفيديو ببطء إذا لم يتم تشغيله تلقائيًا
يُنصح عادةً بتجنُّب تشغيل الفيديوهات تلقائيًا لأنّ ذلك يتيح للمستخدم التحكّم في المحتوى. في هذه الحالات، يكون تحديد السمة preload في العنصر <video> هو أفضل طريقة لتجنُّب تحميل الفيديو بأكمله إلى أن تكون هناك حاجة إليه:
<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
يستخدم المثال السابق السمة preload بالقيمة none لمنع المتصفّحات من التحميل المُسبَق لأي بيانات فيديو، حتى عندما تكون في إطار العرض. تمنح السمة poster العنصر <video> عنصرًا نائبًا يشغل المساحة أثناء تحميل الفيديو.
في معظم المتصفّحات، يكون الإعداد التلقائي preload هو metadata، ويتم التحميل المُسبَق لجزء من الفيديو باستخدام العنوان Content-Range. يمكن أن يؤدي ذلك إلى تنزيل بيانات أكثر من المطلوب، إذ لا يمكن للمتصفحات معرفة وحدات البايت التي يتم تخزين البيانات الوصفية فيها، وقد لا يتم تخزينها في بداية الملف. لذلك، فإنّ أفضل طريقة لتجنُّب تحميل الفيديو هي استخدام preload="none".
يمكن تحسين ذلك بشكلٍ أكبر من خلال التحميل المُسبَق للبيانات الوصفية عندما يمرّر المستخدم مؤشر الماوس فوق الفيديو باستخدام السمة onmouseenter (أو باستخدام معالج الأحداث المكافئ mouseenter):
<video controls
loading="lazy"
preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
ولا يؤدي ذلك إلى تقليل التأخير عند تشغيل الفيديو فحسب، بل يعرض أيضًا مدة الفيديو فور تشغيله.
يمكن أن تكون الفيديوهات من المرشّحين لبرنامج "المحتوى المناسب للمعلنين". سيتم تحميل poster الصورة بشكل أسرع من الفيديو، لذا إذا كانت هذه الصورة مرشّحة لتكون عنصر LCP، عليك استخدام صورة ملصق، ولكن عليك أيضًا تحميلها مسبقًا باستخدام قيمة السمة fetchpriority وهي "high"، لأنّه في وقت كتابة هذا المقال، لا يمكنك تحديد fetchpriority لسمات الملصق:
<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
يجب عدم استخدام loading="lazy" مع الفيديوهات التي تشكّل عناصر LCP، تمامًا كما يجب عدم تحميل فيديوهات LCP بشكل متأخر .
بالنسبة إلى الفيديو الذي يحلّ محل صورة GIF متحركة
تُستخدَم الفيديوهات التي يتم تشغيلها تلقائيًا عادةً لإنشاء صور متحركة سريعة بنمط GIF. على الرغم من أنّ صور GIF المتحرّكة تُستخدَم على نطاق واسع، إلا أنّها أقل جودة من فيديوهات مماثلة من عدة نواحٍ، لا سيما من حيث حجم الملف. يمكن أن يصل حجم صور GIF المتحركة إلى عدة ميغابايت من البيانات. تميل الفيديوهات ذات الجودة المرئية المشابهة إلى أن تكون أصغر بكثير.
لا يكون استخدام العنصر <video> كبديل لملف GIF المتحرّك بسيطًا مثل العنصر <img>. تتضمّن صور GIF المتحرّكة ثلاث خصائص:
- ويتم تشغيلها تلقائيًا عند تحميلها.
- يتم تشغيلها بشكل متكرّر (مع أنّ هذا ليس هو الحال دائمًا).
- لا تتضمّن مقطعًا صوتيًا.
يبدو تحقيق ذلك باستخدام العنصر <video> على النحو التالي:
<video autoplay muted loop playsinline>
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
تتجنّب السمة loading="lazy" تحميل الفيديو إلى أن يصبح قريبًا من إطار العرض. سمات autoplay وmuted وloop لا تحتاج إلى شرح. يجب توفّر playsinline لتفعيل ميزة التشغيل التلقائي على أجهزة iOS.
أصبح لديك الآن بديل صالح للفيديو كصورة GIF يعمل على جميع المنصات. ولكن كيف يمكن تنفيذ التحميل الكسول؟
بالنسبة إلى المتصفّحات التي تتيح ذلك، يُعدّ الرمز loading="lazy" الخيار الأسهل:
<video loading="lazy" autoplay muted loop playsinline>
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
لإتاحة التحميل الكسول للفيديو في المتصفّحات الأخرى، عليك استخدام JavaScript وتعديل ترميز <video> وفقًا لذلك:
<video class="lazy" preload="none" controls muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
ستلاحظ إزالة السمة autoplay وإضافة السمات class="lazy" وpreload="none" وposter، ما يتيح لك تحديد عنصر نائب يشغل مساحة العنصر <video> إلى أن يتم تحميل الفيديو بشكل كسول. بعد ذلك، نستخدم JavaScript Intersection Observer لإعادة تفعيل التشغيل التلقائي:
document.addEventListener("DOMContentLoaded", function() {
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
if ("IntersectionObserver" in window) {
var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(video) {
if (video.isIntersecting) {
video.target.removeAttribute('preload');
video.target.removeAttribute('controls');
video.target.autoplay = true;
video.target.classList.remove("lazy");
lazyVideoObserver.unobserve(video.target);
}
});
});
lazyVideos.forEach(function(lazyVideo) {
lazyVideoObserver.observe(lazyVideo);
});
}
});
باستخدام هذه الطريقة، لا يتم تشغيل الفيديو تلقائيًا بشكلٍ تلقائي، بل فقط عندما يرصد Intersection Observer أنّ الفيديو يدخل إلى إطار العرض. بالإضافة إلى ذلك، تعالج السمة controls الحالات التي يتعذّر فيها تنفيذ JavaScript. يعني ذلك أنّ لديك حلاً للفيديو يحاكي سلوك صور GIF المتحركة، ولكنّه لا يؤدي إلى الاستخدام المكثّف نفسه للبيانات كما تفعل صور GIF المتحركة، ويمكنك تحميل هذا المحتوى بشكل غير متزامن.
مكتبات التحميل الكسول
يمكن أن تساعدك المكتبات التالية في تحميل الفيديو عند الطلب:
- vanilla-lazyload وlozad.js هما خياران خفيفا الوزن للغاية يستخدمان Intersection Observer فقط. وبالتالي، فإنّها تقدّم أداءً عاليًا، ولكن يجب توفيرها قبل أن تتمكّن من استخدامها على المتصفّحات القديمة.
- إذا كنت بحاجة إلى مكتبة تحميل كسول خاصة بـ React، يمكنك استخدام react-lazyload. على الرغم من أنّها لا تستخدم Intersection Observer، إلا أنّها توفّر طريقة مألوفة للتحميل الكسول للصور للمطوّرين الذين اعتادوا تطوير التطبيقات باستخدام React.
كل مكتبة من مكتبات التحميل الكسول هذه موثّقة بشكل جيد، وتتضمّن الكثير من أنماط الترميز لمختلف جهود التحميل الكسول.
مع توفّر السمة loading للعنصر <video> في المزيد من المتصفّحات، نتوقّع أن يقلّ استخدام حلول JavaScript (بما في ذلك المكتبات) لصالح الحلول المضمّنة، باستثناء أولئك الذين يريدون تحكّمًا أكبر من ذلك.