تحسين JavaScript للجهات الخارجية

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

  • تأجيل تحميل النص البرمجي

  • تحميل الموارد غير المهمة بشكل بطيء

  • جارٍ الاتصال مسبقًا بالمصادر المطلوبة

يعرض نموذج التطبيق المضمّن صفحة ويب بسيطة تتضمّن ثلاث ميزات من مصادر تابعة لجهات خارجية:

  • تضمين فيديو

  • مكتبة لتصور البيانات لعرض رسم بياني خطي

  • تطبيق مصغّر لمشاركة المحتوى على وسائل التواصل الاجتماعي

لقطة شاشة للصفحة تتضمّن مراجع من جهات خارجية مميّزة.
موارد تابعة لجهات خارجية في نموذج التطبيق:

ستبدأ بقياس أداء التطبيق ثم ستطبّق كل تقنية لتحسين جوانب مختلفة من أداء التطبيق.

قياس الأداء

افتح أولاً نموذج التطبيق في وضع ملء الشاشة:

  1. انقر على Remix to Edit (إنشاء ريمكس لتعديله) ليصبح المشروع قابلاً للتعديل.
  2. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط على ملء الشاشة ملء الشاشة.

يمكنك إجراء تدقيق أداء Lighthouse على الصفحة لتحديد الأداء الأساسي:

  1. اضغط على Ctrl ‏+ Shift ‏+ J (أو Command ‏+ Option ‏+ J على نظام التشغيل Mac) لفتح DevTools.
  2. انقر على علامة التبويب Lighthouse.
  3. انقر على الأجهزة الجوّالة.
  4. ضَع علامة في مربّع الاختيار الأداء. (يمكنك محو بقية مربّعات الاختيار في قسم "عمليات التدقيق").
  5. انقر على شبكة الجيل الثالث السريعة المحاكية، ووحدة المعالجة المركزية (CPU) أبطأ بأربعة أضعاف.
  6. ضَع علامة في مربّع الاختيار محو مساحة التخزين.
  7. انقر على إجراء عمليات التدقيق.

عند إجراء تدقيق على جهازك، قد تختلف النتائج الدقيقة، ولكن من المفترض أن تلاحظ أنّ وقت سرعة عرض أول محتوى مرئي (FCP) مرتفع جدًا، وأنّ Lighthouse تقترح فرصتَين للتحقيق: القضاء على الموارد التي تمنع العرض والربط المُسبَق بالمصادر المطلوبة. (حتى إذا كانت جميع المقاييس في وضع جيد، سيستمرّ تطبيق التحسينات في تحقيق تحسينات).

لقطة شاشة لتدقيق Lighthouse تعرِض سرعة عرض المحتوى على الصفحة التي تبلغ 2.4 ثانية وفرصتَين: إزالة الموارد التي تمنع العرض والاتصال المُسبَق بالمصادر المطلوبة

تأجيل لغة JavaScript التابعة لجهات خارجية

أوضح تقرير تدقيق إزالة الموارد التي تحظر العرض أنّه يمكنك توفير بعض الوقت من خلال تأجيل نص برمجي قادم من d3js.org:

لقطة شاشة لتدقيق إزالة الموارد التي تحظر العرض مع تمييز النص البرمجي d3.v3.min.js

D3.js هي مكتبة JavaScript لإنشاء تصورات البيانات. يستخدم ملف script.js في نموذج التطبيق دوالّ أداة D3 لإنشاء المخطّط الخطي بتنسيق SVG وإرفاقه بالصفحة. من المهمّ ترتيب العمليات هنا: يجب تنفيذ script.js بعد تحليل المستند وتحميل مكتبة D3، ولهذا السبب يتم تضمينها قبل علامة </body> الإغلاق مباشرةً في index.html.

ومع ذلك، يتم تضمين نص D3 البرمجي في <head> الصفحة، ما يؤدي إلى حظر تحليل باقي المستند:

لقطة شاشة لملف index.html مع تمييز علامة النص البرمجي في الرأس

يمكن لسمتين سحرية إلغاء حظر المحلل اللغوي عند إضافتهما إلى علامة النص البرمجي:

  • تضمن 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، اتّبِع الخطوات التالية:

  1. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط على ملء الشاشة ملء الشاشة.
  2. اضغط على "Control+Shift+J" (أو "Command+Option+J" على نظام التشغيل Mac) لفتح "أدوات مطوري البرامج".
  3. انقر على علامة التبويب الشبكة.
  4. ضَع علامة في مربّع الاختيار إيقاف ذاكرة التخزين المؤقت.
  5. اختَر شبكة الجيل الثالث السريعة في القائمة المنسدلة تقييد السرعة.
  6. إعادة تحميل الصفحة

لقطة شاشة للوحة &quot;الشبكة&quot; في DevTools

تكشف لوحة الشبكة أنّ الصفحة قدّمت 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 لتحميل الفيديو بشكل بطيء

لتحميل الفيديو عندما ينتقل إليه المستخدم، عليك معرفة وقت حدوث ذلك. وهنا يأتي دور واجهة برمجة التطبيقات 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);
    });
  });
  1. لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة ملء الشاشة.
  2. اضغط على Ctrl ‏+ Shift ‏+ J (أو Command ‏+ Option ‏+ J على نظام التشغيل Mac) لفتح DevTools.
  3. انقر على علامة التبويب وحدة التحكم.

جرِّب الانتقال للأعلى أو للأسفل. من المفترض أن تظهر لك قيمة التغيير 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:

مراجعة الاتصال المُسبَق بالمصادر المطلوبة مع تمييز النطاق staticxx.facebook.com

بما أنّه يتم الآن تحميل فيديو YouTube بشكل بطيء، لن يتبقّى سوى staticxx.facebook.com، وهو مصدر التطبيق المصغّر لمشاركة المحتوى على وسائل التواصل الاجتماعي. يمكنك بسهولة إنشاء ربط مبكر بهذا النطاق من خلال إضافة علامة <link> إلى <head> المستند:

  <link rel="preconnect" href="https://staticxx.facebook.com">

إعادة تقييم الأداء

في ما يلي حالة الصفحة بعد التحسين. اتّبِع الخطوات الواردة في قسم قياس الأداء من ورشة رموز البرامج لإجراء عملية تدقيق أخرى في Lighthouse.

تدقيق من خلال Lighthouse يُظهر FCP ثانية واحدة ونتيجة الأداء 99.