في جملة واحدة
ملف HAR هو سجل بصيغة JSON لتفاعل المتصفح مع موقع ويب، يسجل كل طلب واستجابة شبكة بأدق التفاصيل لتحليلها لاحقًا.
المشكلة التي يحلها
تخيل المشهد: مستخدم في آخر الدنيا يراسلك على الخاص: "تطبيقك بطيء جدًا لدرجة لا تُطاق". تجربه بنفسك. التطبيق صاروخي. هو يقول إنه خربان. أنت تقول "شغال عندي زي الفل". وصلنا لطريق مسدود.
هذه هي مشكلة "قال وقلت" الكلاسيكية في تطوير الويب. قبل أدوات المتصفح الحديثة، كان تصحيح أخطاء الشبكة عن بعد كابوسًا من التخمين، والغوص في سجلات السيرفر، ومطالبة المستخدمين غير التقنيين بوصف رسائل خطأ غامضة. حتى مع ظهور أدوات المطور (DevTools) ونافذة Network الرائعة، بقيت المشكلة: البيانات كانت مؤقتة. لم يكن بإمكانك "تعبئتها في زجاجة" وإرسالها إلى زميل بسهولة. لقطة شاشة لمخطط الشلال (waterfall chart) لا تروي القصة كاملة.
وهنا يأتي دور صيغة HTTP Archive، أو HAR. ابتكرتها مجموعة عمل أداء الويب (Web Performance Working Group) في W3C، وصُممت لتكون صيغة قياسية وقابلة للمشاركة لأرشفة معاملات HTTP. إنها المعادل الرقمي لوضع مسجل "صندوق أسود" في متصفح المستخدم.
يحل ملف HAR مشكلة "شغال عندي زي الفل" عن طريق تسجيل محادثة الشبكة بأكملها بين المتصفح والسيرفر أثناء تحميل صفحة ويب معينة. يسجل كل طلب لصورة، أو سكربت، أو خط، أو استدعاء API. يسجل بالضبط ما هي الـ headers التي أُرسلت، والـ cookies التي تم تبادلها، وعمليات إعادة التوجيه (redirects) التي تم اتباعها، والأهم من ذلك، التوقيتات الدقيقة لكل مرحلة من مراحل الطلب.
هذا يسمح لمطور في سان فرانسيسكو أن يرى بالضبط ما جربه مستخدم في سنغافورة، ميللي ثانية بميللي ثانية، دون الحاجة إلى التخمين. يجعل أخطاء الشبكة العابرة التي يصعب إعادة إنتاجها قابلة للتحليل، ويحول الشكاوى الغامضة من "البطء" إلى بيانات قابلة للتنفيذ.
كيف تعمل من الداخل
في جوهره، ملف HAR ليس سحرًا. هو مجرد ملف JSON ضخم ومُنظّم. يمكنك فتحه في محرر نصوص ورؤية كل شيء، على الرغم من أن عارضًا مخصصًا يجعله أسهل بكثير في الفهم. دعنا نلقي نظرة خاطفة على محتوياته.
الهيكل العام: مجرد JSON
يحتوي ملف HAR على كائن JSON واحد في المستوى الأعلى بمفتاح واحد: log. كل شيء آخر يعيش داخل هذا الكائن log.
{
"log": {
"version": "1.2",
"creator": { "name": "Chrome", "version": "118.0.0.0" },
"browser": { "name": "Chrome", "version": "118.0.0.0" },
"pages": [ /* ... one or more page objects ... */ ],
"entries": [ /* ... one or more request/response objects ... */ ]
}
}
version: إصدار مواصفات HAR، عادةً "1.2".creator/browser: بيانات وصفية حول الأداة والمتصفح اللذين أنشآ الملف. مفيدة للسياق.pages: مصفوفة تصف الصفحة أو الصفحات الرئيسية التي تم تحميلها. تتضمن عنوان الصفحة وتوقيتات للأحداث عالية المستوى مثلonLoadوonContentLoad.entries: هذا هو نجم العرض. إنها مصفوفة طويلة حيث يمثل كل كائن طلب شبكة واحد واستجابته المقابلة.
نجم العرض: مصفوفة entries
عندما تحلل ملف HAR، ستقضي 99% من وقتك في entries. كل إدخال (entry) هو ملف كامل عن مورد واحد.
إليك نظرة مبسطة على إدخال واحد:
{
"startedDateTime": "2023-10-27T10:30:05.123Z",
"time": 258.45,
"request": { /* ... details of the request ... */ },
"response": { /* ... details of the response ... */ },
"timings": { /* ... the juicy performance breakdown ... */ },
"pageref": "page_1"
}
startedDateTime: الطابع الزمني الدقيق بالتوقيت العالمي المنسق (UTC) عند بدء الطلب.time: الوقت الإجمالي المستغرق للطلب بالمللي ثانية، من البداية إلى النهاية.request: كائن يحتوي على كل ما أرسله المتصفح إلى السيرفر.response: كائن يحتوي على كل ما أرسله السيرفر обратно.timings: منجم الذهب لتصحيح أخطاء الأداء. سنقوم بتشريحه تاليًا.pageref: معرّف يربط هذا الطلب بإحدىpagesفي مصفوفة الصفحات.
تشريح الطلب والاستجابة (Request and Response)
كائنات request وresponse هي مرآة لما تراه في أدوات المطور (DevTools).
تفاصيل كائن request:
method:GET،POST،PUT، إلخ.url: الرابط الكامل للمورد.headers: مصفوفة بجميع ترويسات الطلب (request headers)، مثلUser-Agent،Accept، وCookie.queryString: مصفوفة بأي معاملات استعلام (query parameters) في الرابط.postData: لطلباتPOST، يحتوي هذا على الحمولة (payload)، مثل بيانات نموذج أو جسم JSON.
تفاصيل كائن response:
status: كود حالة HTTP (مثل200،404،500).statusText: عبارة السبب (مثلOK،Not Found).headers: مصفوفة بجميع ترويسات الاستجابة (response headers)، مثلContent-Type،Cache-Control، وSet-Cookie.content: كائن يصف جسم الاستجابة (response body)، بما في ذلكsize(حجمه)،mimeType(نوعه)، وغالبًا الجسم نفسه في خاصيةtext(على الرغم من أنه يمكن حذفه لتوفير المساحة أو لأسباب أمنية).
تفصيل توقيتات الشلال (Waterfall)
كائن timings هو ما يشغل مخطط الشلال الملون في عارض HAR. إنه يحلل إجمالي time الطلب إلى مراحله المكونة. فهم هذه المراحل هو مفتاح تشخيص "لماذا" كان الطلب بطيئًا.
| التوقيت | ماذا يعني |
|---|---|
blocked |
الوقت الذي قضاه الطلب منتظرًا في طابور المتصفح قبل أن يتمكن حتى من البدء. غالبًا بسبب حدود الاتصال. |
dns |
الوقت المستغرق في بحث DNS. قيمة عالية قد تشير إلى مزود DNS بطيء. |
connect |
الوقت المستغرق لإنشاء اتصال TCP مع السيرفر. يتضمن وقت ssl. |
ssl |
(جزء من connect) وقت مصافحة SSL/TLS. القيم العالية يمكن أن تشير إلى مشاكل في تكوين السيرفر أو الشبكة. |
send |
الوقت المستغرق في إرسال طلب HTTP إلى السيرفر. عادة ما يكون قصيرًا جدًا. |
wait |
Time To First Byte (TTFB). هذا هو المقياس الحاسم. الوقت الذي يقضيه في انتظار السيرفر لمعالجة الطلب وإرسال أول بايت من الاستجابة. وقت wait طويل هو دائمًا مشكلة في الواجهة الخلفية (backend) تقريبًا. |
receive |
الوقت المستغرق في تنزيل جسم الاستجابة من السيرفر. وقت receive طويل لملف صغير قد يشير إلى شبكة بطيئة؛ لملف كبير، هذا متوقع. |
إجمالي time لأي إدخال هو مجموع هذه التوقيتات الفردية (غير السالبة). عندما يعرض لك عارض HAR شريطًا لطلب ما، فإنه يقوم بصريًا بتكديس قيم timings هذه جنبًا إلى جنب.
قصص من الواقع
قضية البطء الغامض
مدير منتج يرسل رسالة محمومة للفريق: "صفحة الدفع الجديدة بطيئة جدًا لأكبر عملائنا! يهددون بالرحيل!" فريق المطورين يجرب عملية الدفع. إنها سريعة كالبرق. العميل يصر على أن تأكيد الطلب يستغرق 20 ثانية. بدلاً من جدال عقيم، يقوم المطور الرئيسي بإرشاد العميل خطوة بخطوة لتصدير ملف HAR.
بمجرد فتح الملف، كانت المشكلة واضحة على الفور. في entries، طلب POST إلى /api/v1/finalize_order له time إجمالي قدره 20,145 مللي ثانية. بالنظر إلى كائن timings، كان wait (TTFB) أكثر من 20,000 مللي ثانية. السيرفر الخلفي كان يستغرق 20 ثانية للرد. اتضح أن هذا العميل المحدد كان لديه تاريخ طلبات ضخم، واستعلام قاعدة بيانات غير محسن كان ينتهي وقته، ولكن فقط لحسابه. قدم ملف HAR الدليل القاطع الذي أشار مباشرة إلى عملية خلفية محددة.
الدرس المستفاد: ملف HAR يلتقط الظروف الخاصة بالمستخدم (مثل بيانات الحساب) التي لا يمكنك تكرارها، محولًا لغزًا إلى تقرير خطأ مستهدف.
الجاني: الحزمة الضخمة (Bloated Bundle)
تم إطلاق موقع تسويقي ومعدل الارتداد (bounce rate) مرتفع جدًا. الموقع يبدو ثقيلًا. مطور واجهة أمامية يفتح الموقع، يفتح أدوات المطور، يسجل جلسة، ويصدر ملف HAR.
في عارض HAR، يقوم بفرز الإدخالات حسب الحجم. في الأعلى يوجد main.acb123.js بحجم هائل يبلغ 5.2 ميجابايت. يُظهر الشلال أنه مورد يحجب العرض (render-blocking)؛ لا يظهر أي شيء على الصفحة حتى ينتهي تنزيل هذا الوحش. وقت receive وحده يستغرق عدة ثوانٍ، حتى على اتصال سريع. والأسوأ من ذلك، بالنظر إلى response headers لهذا الإدخال، يرون أن السيرفر لا يرسل ترويسة Content-Encoding: gzip، على الرغم من أن المتصفح يرسل Accept-Encoding: gzip في request headers. حزمة JavaScript لم تكن تُضغط.
الدرس المستفاد: ملفات HAR تجعل من السهل جدًا اكتشاف قتلة الأداء مثل الأصول كبيرة الحجم وتكوينات السيرفر الخاطئة التي تدمر وقت تحميل صفحتك.
حلقة إعادة التوجيه اللانهائية
مستخدم يشتكي من عدم قدرته على تسجيل الدخول. يدخل بيانات اعتماده، ينقر على "تسجيل الدخول"، ويتم إعادته فورًا إلى صفحة تسجيل الدخول دون أي خطأ. إنها حلقة كلاسيكية. يطلب الدعم من المستخدم ملف HAR لمحاولة تسجيل الدخول.
قائمة entries في HAR تروي قصة واضحة:
POST /loginينجح ويحصل على302 Redirectإلى/dashboard. تتضمن الاستجابة ترويسةSet-Cookieمع توكن الجلسة.- المتصفح يتبع إعادة التوجيه ويقوم بطلب
GET /dashboard. - السيرفر يرد على
GET /dashboardبـ302 Redirectمرة أخرى إلى/login.
لماذا؟ المطور يفحص إدخال طلب GET /dashboard. ترويسة Cookie تفتقد توكن الجلسة. ثم يتحقق من الاستجابة من طلب POST /login الأولي. كانت ترويسة Set-Cookie هي session_id=...; Secure; HttpOnly. علامة Secure تعني أن المتصفح سيرسل الكوكي فقط عبر HTTPS. كان المستخدم على بيئة http://staging.example.com. كان المتصفح يرفض بشكل صحيح إرسال الكوكي الآمن عبر اتصال غير آمن، لذلك لم يره السيرفر مسجلاً للدخول أبدًا.
الدرس المستفاد: تمنحك ملفات HAR إعادة تشغيل مثالية، إطارًا بإطار، لعمليات إعادة توجيه HTTP وتبادل الترويسات، مما يجعل من الممكن تصحيح تدفقات المصادقة المعقدة التي تفشل بصمت.
أخطاء وفخاخ شائعة
- نسيان تفعيل "Preserve log". إذا كان خطأك يتضمن الانتقال من الصفحة A إلى الصفحة B، فيجب عليك تمكين خيار "Preserve log" (أو ما يعادله) في DevTools. وإلا، سيتم مسح السجل عند التنقل، وسيحتوي ملف HAR الخاص بك فقط على طلبات الصفحة B.
- مشاركة البيانات الحساسة. ملفات HAR هي مسجلات لا تميز. ستلتقط مفاتيح API، وتوكنات الجلسة في الكوكيز، والمعلومات الشخصية التعريفية في أجسام POST. قم دائمًا بتنقية ملفات HAR قبل مشاركتها في متتبعات الأخطاء العامة أو المنتديات.
- إساءة تفسير وقت
blocked. وقتblockedمرتفع لا يعني دائمًا أن الشبكة مزدحمة. للمتصفحات حد لعدد الاتصالات المتوازية التي ستفتحها لنطاق واحد (عادة 6). إذا أطلقت 20 طلب صورة دفعة واحدة، فسيظل 14 منها في حالةblocked، في انتظار انتهاء أحد الطلبات الستة الأولى. - تجاهل حالة الكاش (cache). إذا كنت تختبر أداء التحميل الأول، فأنت بحاجة إلى التسجيل مع تعطيل ذاكرة التخزين المؤقت للمتصفح. وإلا، سترى الكثير من استجابات
304 Not Modifiedأو طلبات تكتمل في أقل من ميللي ثانية، وهذا لا يعكس تجربة مستخدم جديد.
لماذا يجب أن تضعه في اعتبارك
يجب أن تفكر في استخدام ملف HAR كلما كان الاتصال الشبكي مشتبهًا به محتملاً.
- عندما يبلغ مستخدم عن مشكلة أداء لا يمكنك إعادة إنتاجها.
- عندما تحتاج إلى تحسين صفحة بطيئة التحميل وتريد تحديد أكبر نقاط الاختناق.
- عندما تقوم بتصحيح تدفق API متعدد الخطوات، مثل تسجيل الدخول عبر OAuth أو عملية دفع، وتحتاج إلى رؤية التسلسل الدقيق للأحداث.
- عندما تحتاج إلى تقديم تقرير خطأ لخدمة طرف ثالث (مثل CDN أو مزود API) وتريد تزويدهم بدليل قاطع على المشكلة. ملف HAR هو اللغة العالمية لمشاكل الشبكة.
تعمق أكثر
- HAR 1.2 Specification: المواصفات الأصلية الفعلية التي تحدد بنية ملفات HAR.
- Google Chrome DevTools: Network features reference: دليل متعمق للأداة الأكثر استخدامًا لإنشاء ملفات HAR.
- MDN Web Docs: Network request list: وثائق موزيلا الممتازة حول تفسير طلبات الشبكة في أدوات المطور الخاصة بـ Firefox.
- What is a HAR File?: نظرة عامة جيدة وعالية المستوى حول كيفية إنشاء واستخدام ملفات HAR لاستكشاف الأخطاء وإصلاحها.