تؤثر النصوص البرمجية التابعة لجهات خارجية في الأداء، ولذلك من المهم تدقيقها بانتظام واستخدام أساليب فعّالة لتحميلها. يعرض لك هذا الدرس التطبيقي كيفية تحسين تحميل المراجع التابعة لجهات خارجية. ويتناول الأساليب التالية:
تأجيل تحميل النص البرمجي
تحميل الموارد غير المهمة باستخدام طريقة "التحميل الكسول"
جارٍ الاتصال مسبقًا بالمصادر المطلوبة
يعرض نموذج التطبيق المضمن صفحة ويب بسيطة بها ثلاث ميزات تأتي من مصادر تابعة لجهات خارجية:
تضمين فيديو
مكتبة تصور البيانات لعرض رسم بياني خطي
تطبيق مصغّر لمشاركة المحتوى على وسائل التواصل الاجتماعي
ستبدأ بقياس أداء التطبيق، ثم ستطبِّق كل أسلوب لتحسين الجوانب المختلفة لأداء التطبيق.
قياس الأداء
افتح أولاً نموذج التطبيق في طريقة العرض بملء الشاشة:
- انقر على إنشاء ريمكس لتعديل لجعل المشروع قابلاً للتعديل.
- لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط ملء الشاشة
يمكنك إجراء تدقيق أداء Lighthouse على الصفحة لتحديد الأداء الأساسي:
- اضغط على "Control+Shift+J" (أو "Command+Option+J" على أجهزة Mac) لفتح "أدوات مطوري البرامج".
- انقر على علامة التبويب Lighthouse.
- انقر على الأجهزة الجوّالة.
- ضع علامة في مربّع الاختيار الأداء. (يمكنك محو بقية مربّعات الاختيار في قسم "عمليات التدقيق").
- انقر على محاكاة شبكة الجيل الثالث السريعة، 4x بطء وحدة المعالجة المركزية (CPU).
- ضَع علامة في مربّع الاختيار محو مساحة التخزين.
- انقر على إجراء عمليات التدقيق.
عند إجراء عملية تدقيق على جهازك، قد تختلف النتائج الدقيقة، ولكن من المفترض أن تلاحظ أنّ مدة سرعة عرض أوّل محتوى (FCP) مرتفعة جدًا، وتقترح أداة Lighthouse فرصتَين للتحقيق فيهما، وهما: إزالة الموارد التي تحظر العرض والاتصال المسبق بالمصادر المطلوبة. (حتى إذا كانت جميع المقاييس باللون الأخضر، ستظل التحسينات تؤدي إلى تحسينات).
تأجيل لغة JavaScript التابعة لجهات خارجية
حددت عملية التدقيق إزالة الموارد التي تحظر العرض أنه يمكنك توفير بعض الوقت من خلال تأجيل نص برمجي قادم من d3js.org:
D3.js هي مكتبة JavaScript لإنشاء العروض المرئية للبيانات. يستخدم ملف script.js
في نموذج التطبيق وظائف الأداة D3 لإنشاء رسم بياني خطي بتنسيق SVG وإلحاقه بالصفحة. من المهم ترتيب العمليات هنا: يجب تشغيل script.js
بعد تحليل المستند وتحميل مكتبة D3، ولذلك يتم تضمينها قبل علامة الإغلاق </body>
في index.html
مباشرةً.
ومع ذلك، يتم تضمين النص البرمجي D3 في <head>
للصفحة، ما يمنع تحليل باقي المستند:
يمكن لسمتين سحرية إلغاء حظر المحلل اللغوي عند إضافتهما إلى علامة النص البرمجي:
تضمن
async
تنزيل النصوص البرمجية في الخلفية وتنفيذها في أول فرصة بعد انتهاء تنزيلها.يضمن
defer
تنزيل النصوص البرمجية في الخلفية وتنفيذها بعد اكتمال التحليل.
بما أنّ هذا الرسم البياني ليس مهمًا للصفحة بأكملها وسيكون على الأرجح الجزء السفلي غير المرئي من الصفحة، يمكنك استخدام defer
للتأكّد من عدم حظر المحلِّل اللغوي.
الخطوة 1: تحميل النص البرمجي بشكل غير متزامن مع السمة defer
في السطر 17 من index.html
، أضِف السمة defer
إلى العنصر <script>
:
<script src="https://d3js.org/d3.v3.min.js" defer></script>
الخطوة 2: التأكّد من الترتيب الصحيح للعمليات
الآن بعد تأجيل D3، سيتم تنفيذ script.js
قبل أن يصبح D3 جاهزًا، ما يؤدي إلى حدوث خطأ.
يتم تنفيذ النصوص البرمجية التي تتضمّن السمة defer
بالترتيب الذي تم تحديدها به. لضمان تنفيذ script.js
بعد أن يصبح D3 جاهزًا، أضِف defer
إليه وانقله إلى <head>
في المستند، بعد عنصر <script>
D3 مباشرةً. والآن لم يعد يحظر المحلل اللغوي، وسيبدأ التنزيل بشكل أسرع.
<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>
مراجع تابعة لجهات خارجية تستخدم التحميل الكسول
تكون جميع الموارد المتوفّرة في الجزء السفلي غير المرئي من الصفحة مناسبة تمامًا للتحميل الكسول.
يحتوي نموذج التطبيق على فيديو YouTube مضمّن في iframe. للاطّلاع على عدد الطلبات التي ترسلها الصفحة وتلك التي يتم الحصول عليها من إطار iframe في YouTube، يُرجى اتّباع الخطوات التالية:
- لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط ملء الشاشة
- اضغط على "Control+Shift+J" (أو "Command+Option+J" على أجهزة Mac) لفتح "أدوات مطوري البرامج".
- انقر على علامة التبويب الشبكة.
- ضع علامة في مربّع الاختيار إيقاف ذاكرة التخزين المؤقت.
- اختَر Fast 3G (شبكة الجيل الثالث السريع) في القائمة المنسدلة Throttling.
- إعادة تحميل الصفحة
تكشف لوحة الشبكة أنّ الصفحة قدّمت 28 طلبًا إجمالاً ونقلت 1 ميغابايت تقريبًا من الموارد المضغوطة.
لتحديد الطلبات المقدَّمة من "iframe
" على YouTube، ابحث عن معرّف الفيديو 6lfaiXM6waw
في عمود المبدئ. لتجميع كل الطلبات معًا حسب النطاق:
في لوحة الشبكة، انقر بزر الماوس الأيمن على عنوان عمود.
في القائمة المنسدلة، اختَر عمود النطاقات.
لترتيب الطلبات حسب النطاق، انقر على عنوان عمود النطاقات.
يكشف الترتيب الجديد عن وجود طلبات إضافية لنطاقات Google. يقدم إطار iframe في YouTube إجمالاً 14 طلبًا للنصوص البرمجية وأوراق الأنماط والصور والخطوط. ولكن ما لم يقوم المستخدمون بالتمرير لأسفل لتشغيل الفيديو، فلن يحتاجون حقًا إلى كل مواد العرض هذه.
من خلال الانتظار قبل التحميل الكسول للفيديو إلى أن ينتقل المستخدم للأسفل إلى ذلك القسم من الصفحة، يتم خفض عدد الطلبات التي تجريها الصفحة في البداية. يوفر هذا الأسلوب البيانات وزيادة التحميل الأولي.
ويتم تنفيذ طريقة "التحميل الكسول" من خلال استخدام Intersection Observer، وهي واجهة برمجة تطبيقات خاصة بالمتصفّح تُعلِمك عند دخول عنصر إلى إطار عرض المتصفّح أو الخروج منه.
الخطوة 1: منع تحميل الفيديو في البداية
لإجراء تحميل كسول لإطار iframe للفيديو، عليك أولاً منع تحميله بالطريقة المعتادة. يمكنك إجراء ذلك من خلال استبدال السمة src
بالسمة data-src
لتحديد عنوان URL الخاص بالفيديو:
<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
data-src
هي سمة بيانات تتيح لك تخزين معلومات إضافية على عناصر HTML العادية. يمكن تسمية سمة البيانات بأي شيء، طالما أنها تبدأ بـ "data-".
يتعذّر تحميل إطار iframe بدون src
.
الخطوة 2: استخدام أداة "مراقبة التقاطع" لتحميل الفيديو الكسول
عليك معرفة وقت حدوث ذلك لتحميل الفيديو عندما ينتقل المستخدم إليه. وهنا يأتي دور واجهة برمجة تطبيقات Intersection Observer API. تتيح لك Intersection Observer API تسجيل دالة استدعاء يتم تنفيذها عندما يدخل عنصر تريد تتبُّعه إلى إطار العرض أو يخرج منه.
للبدء، يجب إنشاء ملف جديد وتسميته باسم lazy-load.js
:
- انقر على ملف جديد وأدخِل اسمًا له.
- انقر على إضافة هذا الملف.
أضف علامة النص البرمجي إلى رأس المستند:
<script src="/lazy-load.js" defer></script>
في lazy-load.js
، أنشئ IntersectionObserver
جديدة وأرسِلها كدالة استدعاء لتشغيلها:
// create a new Intersection Observer
let observer = new IntersectionObserver(callback);
يمكنك الآن منح observer
عنصرًا مستهدفًا لمشاهدته (إطار iframe للفيديو في هذه الحالة) من خلال تمريره كوسيطة في طريقة observe
:
// the element that you want to watch
const element = document.querySelector('iframe');
// register the element with the observe method
observer.observe(element);
تتلقّى callback
قائمة بكائنات IntersectionObserverEntry
والكائن IntersectionObserver
نفسه. يحتوي كل إدخال على عنصر target
وخصائصه التي تصف أبعاده وموضعه ووقت دخوله إلى إطار العرض، وغيرها. إحدى سمات IntersectionObserverEntry
هي isIntersecting
، وهي قيمة منطقية تساوي true
عندما يدخل العنصر إلى إطار العرض.
في هذا المثال، تمثّل السمة target
السمة iframe
. تساوي isIntersecting
true
عندما تدخل target
في إطار العرض. للاطّلاع على ذلك عمليًا، استبدِل callback
بالدالة التالية:
let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
- لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط ملء الشاشة
- اضغط على "Control+Shift+J" (أو "Command+Option+J" على أجهزة Mac) لفتح "أدوات مطوري البرامج".
- انقر على علامة التبويب وحدة التحكم.
جرِّب الانتقال للأعلى وللأسفل. من المفترض أن تظهر لك قيمة التغيير isIntersecting
والعنصر الهدف المسجَّل في وحدة التحكّم.
لتحميل الفيديو عندما ينتقل المستخدم إلى موضعه، استخدِم isIntersecting
كشرط لتشغيل الدالة loadElement
التي تحصل على القيمة من data-src
في العنصر iframe
وتضبطها كسمة src
للعنصر iframe
. يؤدي هذا الاستبدال إلى تحميل الفيديو. بعد ذلك، بعد تحميل الفيديو، يمكنك استدعاء الإجراء unobserve
على observer
للتوقّف عن مشاهدة العنصر الهدف:
let observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
if (entry.isIntersecting) {
// do this when the element enters the viewport
loadElement(entry.target);
// stop watching
observer.unobserve(entry.target);
}
});
});
function loadElement(element) {
const src = element.getAttribute('data-src');
element.src = src;
}
الخطوة 3: إعادة تقييم الأداء
لمعرفة مدى تغيُّر حجم الموارد وعددها، افتح لوحة الشبكة في "أدوات مطوري البرامج" وأعِد تحميل الصفحة مرة أخرى. توضّح لوحة الشبكة أنّ الصفحة قدّمت 14 طلبًا بحجم 260 كيلوبايت فقط. هذا تحسُّن مفيد.
الآن انتقِل إلى أسفل الصفحة وراقِب لوحة الشبكة. عندما تصل إلى الفيديو، من المفترض أن تظهر الصفحة تطلب منك إرسال طلبات إضافية.
الاتصال المسبق بالمصادر المطلوبة
لقد أجَّلت محتوى JavaScript غير المهم وحمّلت طلبات YouTube بشكل كسول، لذا حان الوقت الآن لتحسين المحتوى المتبقي التابع لجهات خارجية.
عند إضافة السمة rel=preconnect
إلى رابط، يتم توجيه المتصفّح لإنشاء اتصال بنطاق قبل تقديم طلب الوصول إلى هذا المورد. يتم استخدام هذه السمة بشكل أفضل مع المصادر التي توفّر الموارد التي تحتاجها الصفحة.
تدقيق Lighthouse الذي أجريته في الخطوة الأولى، والذي اقترحه في الاتصال المسبق بالمصادر المطلوبة، والذي يمكنك توفيره حوالي 400 ملي ثانية من خلال إنشاء اتصالات مبكرة بكل من staticxx.facebook.com وyoutube.com:
ولأنّ الفيديو على YouTube أصبح الآن بالتحميل الكسول، ما يعني أنّ الموقع الإلكتروني staticxx.facebook.com هو مصدر أداة المشاركة على وسائل التواصل الاجتماعي. يمكن إنشاء اتصال مبكرًا بهذا النطاق بسهولة من خلال إضافة علامة <link>
إلى العنصر <head>
في المستند:
<link rel="preconnect" href="https://staticxx.facebook.com">
إعادة تقييم الأداء
في ما يلي حالة الصفحة بعد التحسين. اتّبِع الخطوات الواردة في قسم قياس الأداء في الدرس التطبيقي حول الترميز لإجراء تدقيق آخر في Lighthouse.