تعرَّف على أساسيات استخدام واجهات برمجة تطبيقات التنقّل وتوقيت الموارد لتقييم أداء التحميل في الحقل.
تاريخ النشر: 8 تشرين الأول (أكتوبر) 2021
إذا كنت قد استخدمت ميزة الحدّ من سرعة الاتصال في لوحة الشبكة ضمن أدوات المطوّرين في المتصفّح (أو Lighthouse في Chrome) لتقييم أداء التحميل، ستدرك مدى ملاءمة هذه الأدوات لتحسين الأداء. يمكنك قياس تأثير تحسينات الأداء بسرعة باستخدام سرعة اتصال أساسية متّسقة وثابتة. المشكلة الوحيدة هي أنّ هذا الاختبار اصطناعي، ما يؤدي إلى الحصول على بيانات مختبرية، وليس بيانات ميدانية.
الاختبار الاصطناعي ليس سيئًا بطبيعتها، ولكنه لا يمثّل سرعة تحميل موقعك الإلكتروني للمستخدمين الفعليين. يتطلّب ذلك بيانات ميدانية يمكنك جمعها من واجهتَي برمجة التطبيقات Navigation Timing وResource Timing API.
واجهات برمجة تطبيقات لمساعدتك في تقييم أداء التحميل في الحقل
وقت التنقل وتوقيت الموارد هما واجهتا برمجة تطبيقات متشابهتان مع تداخل كبير يقيسان شيئين مختلفين:
- يقيس وقت التنقل سرعة الطلبات لمستندات HTML (أي طلبات التنقل).
- تقيس مُدد تحميل الموارد سرعة طلبات الموارد التي تعتمد على المستندات، مثل ملفات CSS وJavaScript والصور وأنواع الموارد الأخرى.
تعرض واجهات برمجة التطبيقات هذه بياناتها في مخازن مؤقتة لإدخالات الأداء، ويمكن الوصول إليها في المتصفّح باستخدام JavaScript. هناك عدة طرق لطلب البحث في المخزن المؤقت للأداء، ولكن الطريقة الشائعة هي استخدام performance.getEntriesByType
:
// Get Navigation Timing entries:
performance.getEntriesByType('navigation');
// Get Resource Timing entries:
performance.getEntriesByType('resource');
تقبل performance.getEntriesByType
سلسلة تصف نوع الإدخالات التي تريد استرجاعها من مخزن مؤقت لإدخالات الأداء. يسترد 'navigation'
و'resource'
توقيتات واجهتَي برمجة تطبيقات وقت التنقل وتوقيت الموارد على التوالي.
يمكن أن تكون كمية المعلومات التي تقدّمها واجهات برمجة التطبيقات هذه ساحقة، ولكنّها هي مفتاحك لقياس أداء التحميل في الميدان، لأنّه يمكنك جمع هذه التوقيتات من المستخدمين أثناء زيارتهم لموقعك الإلكتروني.
مدة طلب الشبكة وموعد تنفيذه
يشبه جمع وتحليل توقيتات التنقل والموارد الآثار في أنك تعيد بناء الحياة المؤقتة لطلب الشبكة بعد حدوثها. من المفيد أحيانًا الاطّلاع على المفاهيم بشكل مرئي، ويمكن أن تساعدك أدوات المطوّرين في متصفحك في ما يتعلّق بطلبات الشبكة.
تمر عمر طلب الشبكة بمراحل مختلفة، مثل بحث نظام أسماء النطاقات وإنشاء الاتصال وتفاوض بروتوكول أمان طبقة النقل ومصادر أخرى لوقت الاستجابة. يتم عرض هذه التوقيتات على شكل DOMHighResTimestamp
. استنادًا إلى المتصفّح الذي تستخدمه، قد تصل دقة التوقيتات إلى الميكرو ثانية، أو قد يتم تقريبها إلى أجزاء من الثانية. عليك فحص هذه المراحل بالتفصيل ومعرفة مدى ارتباطها بـ "توقيت التنقّل" و"توقيت تحميل الموارد".
بحث نظام أسماء النطاقات
عندما ينتقل المستخدم إلى عنوان URL، يتم الاستعلام عن نظام أسماء النطاقات (DNS) لترجمة أحد المجالات إلى عنوان IP. قد تستغرق هذه العملية وقتًا كبيرًا - وقت ستحتاج فيه إلى قياسه في المجال، حتى. يعرض مقياسا "توقيت التنقّل" و"توقيت الموارد" مقياسَين زمنيَّين مرتبطَين بنظام أسماء النطاقات:
domainLookupStart
هو وقت بدء البحث في نظام أسماء النطاقات.domainLookupEnd
هو عند انتهاء بحث نظام أسماء النطاقات.
يمكن احتساب إجمالي وقت البحث في نظام أسماء النطاقات من خلال طرح مقياس البدء من مقياس النهاية:
// Measuring DNS lookup time
const [pageNav] = performance.getEntriesByType('navigation');
const totalLookupTime = pageNav.domainLookupEnd - pageNav.domainLookupStart;
التفاوض على الاتصال
من العوامل الأخرى التي تساهم في أداء التحميل هي التفاوض على الاتصال، وهو وقت الاستجابة الذي يتم تسجيله عند الاتصال بخادم ويب. إذا كان HTTPS متوفّرًا، ستتضمّن هذه العملية أيضًا وقت التفاوض على بروتوكول أمان طبقة النقل (TLS). تتألف مرحلة الاتصال من ثلاثة مُدد زمنية:
- يحدث
connectStart
عندما يبدأ المتصفّح في فتح الاتصال بخادم ويب. - تشير القيمة
secureConnectionStart
إلى الوقت الذي يبدأ فيه العميل تفاوض بروتوكول أمان طبقة النقل (TLS). connectEnd
هو رمز الاتصال بخادم الويب.
يشبه قياس وقت الاتصال الإجمالي قياس إجمالي وقت بحث نظام أسماء النطاقات: تطرح توقيت البدء من توقيت الانتهاء. ومع ذلك، هناك سمة secureConnectionStart
إضافية قد تكون 0
في حال عدم استخدام بروتوكول HTTPS أو في حال استمرار الاتصال. إذا أردت قياس وقت التفاوض على بروتوكول TLS، عليك مراعاة ما يلي:
// Quantifying total connection time
const [pageNav] = performance.getEntriesByType('navigation');
const connectionTime = pageNav.connectEnd - pageNav.connectStart;
let tlsTime = 0; // <-- Assume 0 to start with
// Was there TLS negotiation?
if (pageNav.secureConnectionStart > 0) {
// Awesome! Calculate it!
tlsTime = pageNav.connectEnd - pageNav.secureConnectionStart;
}
بعد انتهاء بحث نظام أسماء النطاقات والتفاوض على الاتصال، يتم تفعيل التوقيتات المتعلقة بجلب المستندات والموارد التابعة لها.
الطلبات والردود
يتأثر أداء التحميل بنوعَين من العوامل:
- العوامل الخارجية: تشمل هذه العوامل وقت الاستجابة وسعة النطاق. بالإضافة إلى اختيار شركة استضافة وربما شبكة توصيل محتوى (CDN)، تقع هذه الأمور (في الغالب) خارج نطاق سيطرتنا، إذ يمكن للمستخدمين الوصول إلى الويب من أي مكان.
- العوامل الأساسية: تشمل هذه العوامل التصاميم من جهة الخادم والعميل، بالإضافة إلى حجم الموارد وقدرتنا على تحسين هذه العوامل التي يمكننا التحكّم فيها.
يؤثر كلا نوعَي العوامل في أداء التحميل. تعتبر التوقيتات المتعلقة بهذه العوامل أمرًا حيويًا، لأنها تصف المدة التي تستغرقها الموارد لتنزيلها. يصف كلّ من "توقيت التنقّل" و"توقيت الموارد" أداء التحميل باستخدام المقاييس التالية:
- تشير السمة
fetchStart
إلى الوقت الذي يبدأ فيه المتصفّح في استرجاع مورد (وقت الموارد) أو مستند لطلب تنقُّل (وقت التنقل). ويسبق ذلك الطلب الفعلي، وهو النقطة التي يتحقّق فيها المتصفّح من ذاكرات التخزين المؤقت (على سبيل المثال، مثيلا HTTP وCache
). - تشير السمة
workerStart
إلى وقت بدء معالجة طلب ضمن معالِج حدثfetch
الخاص بعامل الخدمة. سيكون هذا العنصر0
عندما لا يتحكّم أي مشغّل خدمات في الصفحة الحالية. requestStart
هو وقت تقديم المتصفّح للطلب.responseStart
هو وقت وصول أول بايت من الاستجابة.responseEnd
هو وقت وصول البايت الأخير من الاستجابة.
تتيح لك هذه المُدد الزمنية قياس جوانب متعدّدة من أداء التحميل، مثل البحث في ذاكرة التخزين المؤقت ضمن عامل خدمة و مدّة التنزيل:
// Cache seek plus response time of the current document
const [pageNav] = performance.getEntriesByType('navigation');
const fetchTime = pageNav.responseEnd - pageNav.fetchStart;
// Service worker time plus response time
let workerTime = 0;
if (pageNav.workerStart > 0) {
workerTime = pageNav.responseEnd - pageNav.workerStart;
}
يمكنك أيضًا قياس جوانب أخرى من وقت استجابة الطلب والاستجابة:
const [pageNav] = performance.getEntriesByType('navigation');
// Request time only (excluding redirects, DNS, and connection/TLS time)
const requestTime = pageNav.responseStart - pageNav.requestStart;
// Response time only (download)
const responseTime = pageNav.responseEnd - pageNav.responseStart;
// Request + response time
const requestResponseTime = pageNav.responseEnd - pageNav.requestStart;
قياسات أخرى يمكنك إجراؤها
يُعدّ مقياسا "توقيت التنقّل" و"توقيت تحميل الموارد" مفيدَين لأكثر من ما توضّحه الأمثلة السابقة. فيما يلي بعض المواقف الأخرى ذات التوقيتات ذات الصلة التي قد تستحق الاستكشاف:
- عمليات إعادة توجيه الصفحة: عمليات إعادة التوجيه هي مصدر مهمل للتأخير الإضافي، لا سيما سلاسل عمليات إعادة التوجيه. تتم إضافة وقت الاستجابة بعدة طرق، مثل عمليات القفزة من HTTP إلى HTTPS، بالإضافة إلى عمليات إعادة التوجيه 302/301 غير المخزّنة مؤقتًا. تكون أوقات
redirectStart
وredirectEnd
وredirectCount
مفيدة في تقييم وقت استجابة إعادة التوجيه. - إلغاء تحميل المستند: في الصفحات التي تشغِّل الرمز في معالِج أحداث
unload
، يجب أن ينفّذ المتصفّح هذا الرمز قبل الانتقال إلى الصفحة التالية. يقيسunloadEventStart
وunloadEventEnd
تفريغ المستندات. - معالجة المستندات: قد لا تكون معالجة المستندات ذات تأثير كبير ما لم يُرسِل موقعك الإلكتروني حمولات HTML كبيرة جدًا. إذا كان هذا الوصف يناسب حالتك، قد تهمّك أوقات
domInteractive
وdomContentLoadedEventStart
وdomContentLoadedEventEnd
وdomComplete
.
كيفية الحصول على التوقيتات في الرمز
تستخدم جميع الأمثلة المعروضة حتى الآن السمة performance.getEntriesByType
، ولكن هناك طرق أخرى لطلب البحث عن المخزن المؤقت لإدخال الأداء، مثل performance.getEntriesByName
وperformance.getEntries
. هذه الطرق جيدة عند الحاجة فقط إلى تحليل الضوء. وفي حالات أخرى، يمكن أن تؤدي إلى زيادة كبيرة في عمل سلسلة المهام الرئيسية من خلال تكرار عدد كبير من الإدخالات، أو حتى إجراء عمليات استطلاع متكررة لمخازن الأداء للعثور على إدخالات جديدة.
والأسلوب المُقترَح لجمع الإدخالات من المخزن المؤقت لإدخال الأداء هو استخدام PerformanceObserver
. يرصد PerformanceObserver
إدخالات الأداء ويوفرها عند إضافتها إلى المخزن المؤقت:
// Create the performance observer:
const perfObserver = new PerformanceObserver((observedEntries) => {
// Get all resource entries collected so far:
const entries = observedEntries.getEntries();
// Iterate over entries:
for (let i = 0; i < entries.length; i++) {
// Do the work!
}
});
// Run the observer for Navigation Timing entries:
perfObserver.observe({
type: 'navigation',
buffered: true
});
// Run the observer for Resource Timing entries:
perfObserver.observe({
type: 'resource',
buffered: true
});
قد تبدو طريقة جمع التوقيتات هذه غير ملائمة مقارنةً بالوصول مباشرةً إلى ذاكرة التخزين المؤقت لإدخال الأداء، ولكن يُفضَّل ربط الخيط الرئيسي بعمل لا يخدم غرضًا مهمًا موجهًا للمستخدم.
كيفية الاتصال بالمنزل
بعد جمع كلّ الأوقات التي تحتاجها، يمكنك إرسالها إلى نقطة نهاية لإجراء المزيد من التحليل. وتتوفر طريقتان لإجراء ذلك، وهما استخدام navigator.sendBeacon
أو fetch
مع ضبط الخيار keepalive
. ستُرسِل كلتا الطريقتَين طلبًا إلى نقطة نهاية محدّدة بطريقة غير حظر، وسيتم وضع الطلب في قائمة الانتظار بطريقة تتجاوز جلسة الصفحة الحالية إذا لزم الأمر:
// Check for navigator.sendBeacon support:
if ('sendBeacon' in navigator) {
// Caution: If you have lots of performance entries, don't
// do this. This is an example for illustrative purposes.
const data = JSON.stringify(performance.getEntries());
// Send the data!
navigator.sendBeacon('/analytics', data);
}
في هذا المثال، ستصل سلسلة JSON إلى حمولة POST
يمكنك فك ترميزها ومعالجتها وتخزينها في واجهة خلفية للتطبيق حسب الحاجة.
الخاتمة
بعد جمع المقاييس، عليك تحديد كيفية تحليل بيانات الحقل هذه. عند تحليل بيانات الحقل، هناك بعض القواعد العامة التي يجب اتباعها لضمان استخلاص استنتاجات مفيدة:
- تجنَّب استخدام القيم المتوسطة، لأنّها لا تمثّل تجربة أي مستخدم، وقد تكون منحرفة بسبب القيم الشاذة.
- الاعتماد على النِسب المئوية في مجموعات بيانات مقاييس الأداء المستندة إلى الوقت، تكون القيمة أقل أفضل. وهذا يعني أنّك عند إعطاء الأولوية للنسب المئوية المنخفضة، لن تهتم إلا بالتجارب الأسرع.
- أعطِ الأولوية للقيم الأقل تكرارًا. عند إعطاء الأولوية للتجارب التي تقع في الشريحة المئوية التسعون أو أعلى، فإنّك تركّز على ما يهمّك: التجارب الأبطأ.
لا يهدف هذا الدليل إلى أن يكون موردًا شاملاً عن التنقل أو توقيت الموارد، ولكنه نقطة بداية. في ما يلي بعض المراجع الإضافية التي قد تجدها مفيدة:
- مواصفات توقيت التنقّل
- مواصفات توقيت الموارد
- ResourceTiming في الممارسة
- Navigation Timing API (MDN)
- Resource Timing API (MDN)
باستخدام واجهات برمجة التطبيقات هذه والبيانات التي تقدّمها، ستتمكّن من فهم تجربة المستخدمين الفعلية لأداء التحميل، ما سيمنحك ثقة أكبر في تشخيص مشاكل أداء التحميل ومعالجتها في الميدان.