Soft Navigations: قياس أداء تطبيقات الصفحة الواحدة بطريقة المتصفح
تتيح أساليب soft navigation في Chrome أخيرًا لمؤشرات Core Web Vitals أن ترتبط بتغييرات المسار في جانب العميل. إليك كيف تعمل الواجهة البرمجية وكيف تقيسها دون مراقبة.
طوال عقد كامل، لم تكن مؤشرات Core Web Vitals تصف سوى الصفحة الأولى التي يحمّلها الزائر. أما كل تغيير في المسار بعد ذلك داخل تطبيق الصفحة الواحدة فكان غير مرئي للمؤشرات. تجربة soft navigations في Chrome تسدّ هذه الفجوة، وتغيّر الطريقة التي ينبغي بها لأداة تحليلات تضع الخصوصية أولًا أن تقيس الأداء الحقيقي للمستخدم.
النقطة العمياء التي تعالجها soft navigations
تقوم hard navigation التقليدية بإلغاء تحميل المستند وتحميل مستند جديد. يعيد المتصفح ضبط الخط الزمني للأداء، ويُطلق LCP جديدًا، ويبدأ بعدّ CLS وINP من الصفر. وأدوات الميدان مثل CrUX تنسب كل شيء إلى ذلك الـ URL الواحد.
لا تعمل تطبيقات الصفحة الواحدة بهذه الطريقة. فبعد التحميل الأولي، يقوم React Router أو App Router في Next.js أو SvelteKit باستبدال المحتوى في مكانه عبر History API. لا يُلغى تحميل أي مستند، فلا يبدأ أي خط زمني جديد للأداء. وقد يتنقل المستخدم عبر عشر "صفحات" بينما يظل كل مؤشر من Core Web Vitals مثبّتًا على عنوان الدخول.
النتيجة معروفة لكل من دقّق في تطبيق صفحة واحدة: يبدو مسار الوصول سريعًا، بينما لا تظهر أبدًا في البيانات تلك التفاعلات البطيئة في عمق التطبيق.
كيف يكتشف Chrome عملية soft navigation
تشترط أساليب Chrome حدوث ثلاثة أمور بالترتيب قبل تسجيل soft navigation:
- أن يبدأ التنقل بتفاعل من المستخدم — نقرة أو ضغطة مفتاح.
- أن يُعدَّل الـ URL عبر History API أو Navigation API.
- أن يتبع التفاعلَ تعديلٌ في الـ DOM يغيّر عنصرًا موجودًا مسبقًا في الـ DOM.
هذا التسلسل صارم عن قصد. فاستدعاء pushState في الخلفية لأغراض التحليلات، أو شريط عرض ينتقل تلقائيًا، أو تغيير في الـ URL دون تفاعل، لا يستوفي الشرط. وهذه الدقة مهمة: فهي تعني أن soft navigation تقابل شيئًا فعله إنسان حقًا، لا نشاطًا عرضيًا لأحد السكربتات.
واجهة الـ API
تظهر soft navigations عبر الـ PerformanceObserver القياسي باستخدام نوع إدخال مخصّص. وتختار تفعيلها لكل observer على حدة:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.startTime);
}
}).observe({ type: "soft-navigation", buffered: true });
والأهم أن إدخالات الأداء الأخرى تكتسب navigationId. فإدخالات LCP وlayout-shift وevent-timing الصادرة بعد soft navigation تحمل المعرّف الجديد، ما يتيح لك إعادة نسب كل مؤشر من Core Web Vitals إلى المسار الذي كان المستخدم عليه فعلًا:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// entry.navigationId يربط هذا LCP بعملية soft navigation محددة
send({ metric: "LCP", value: entry.startTime, navId: entry.navigationId });
}
}).observe({ type: "largest-contentful-paint", buffered: true });
يعيش هذا اليوم خلف chrome://flags/#soft-navigation-heuristics وتجربة origin trial، مع ظهور محدود في CrUX. وهو ليس بعدُ السلوك الافتراضي في إصدار Chrome المستقر، فتعامل مع أرقام الميدان بوصفها إرشادية لا مرجعية قاطعة. وتعرض مكتبة web-vitals البيانات نفسها عبر خيار reportSoftNavs، وهو الطريقة العملية لربط كل ذلك دون كتابة observers يدويًا.
لماذا ينتمي هذا إلى تحليلات تضع الخصوصية أولًا
بيانات soft navigation هي توقيت محض. لا تتضمن معرّفًا، ولا ملف تعريف ارتباط، ولا أي شيء يبقى بعد جلسة الصفحة — مجرد مدة، ونوع عنصر تقريبي، ومسار توجيه. وهذا تحديدًا نوع الإشارة الذي يمكن لأداة بلا ملفات تعريف ارتباط أن تجمعه دون المساس بآلية الموافقة.
يربط المتعقّب نفسه بالفعل بـ history.pushState لعدّ تغييرات المسار في تطبيقات الصفحة الواحدة. وتنقّح soft navigations هذا الربط ذاته: فبدلًا من السؤال فقط هل تغيّر المسار، يمكنك السؤال هل كان هذا تنقّلًا مدفوعًا بتفاعل، وكيف كان أداؤه. وتنتقل إدخالات الأداء جنبًا إلى جنب مع نبضة pageview القائمة إلى /collect، فتضيف قياسًا ميدانيًا دون أن تثقل السكربت الأقل من 2 كيلوبايت، ودون أن تكسر نموذج الهوية القائم على التجزئة اليومية.
الفخّ الذي ينبغي تجنّبه هو معاملة soft navigations كذريعة لجمع المزيد. فبعض مزوّدي RUM سيستخدمون هذا النسب الجديد لخياطة رحلات تنقّل لكل مستخدم عبر جلسة كاملة — وهو بالضبط نمط المراقبة الذي وُجدت التحليلات بلا ملفات تعريف ارتباط لرفضه. وقيمة المؤشر تنبع تحديدًا من قدرته على البقاء مجمَّعًا: الوسيط لـ INP لكل مسار، وتوزيع LCP لكل مسار، دون أي طريق يعود إلى شخص بعينه.
تجعل soft navigations أعمق أجزاء تطبيقك وأبطأها قابلة للقياس لأول مرة. اجمع التوقيت، وأسقط كل ما عداه، فتحصل على صورة الأداء دون الملف الشخصي.