المستوى المطلوب: مبتدئ
Resource Hints: 4 سطور HTML بتقطع 280ms من زمن تحميل صفحتك
لو صفحتك بتحمّل خطوط من Google Fonts، أو صورة كبيرة في الـ hero section، أو بتنادي API على دومين تاني، أول زيارة بتدفع من 180 لـ 480 مللي ثانية ضايعة في حاجة المستخدم مش شايفها أصلاً: تجهيز الاتصال. الخبر الحلو إن في 4 سطور HTML، اسمها Resource Hints، بتقول للمتصفح: "ابدأ التحضير من دلوقتي بدل ما تستنى لما الكود يحتاج المورد". النتيجة بتظهر مباشرة في First Contentful Paint وبتتحسن بنسبة تتراوح بين 20% و 40% على الموبايل.
المشكلة باختصار
لما المتصفح يلاقي صورة أو خط من دومين خارجي زي fonts.gstatic.com، بيعمل 3 خطوات تسلسلية قبل ما أول بايت من المورد يطلع:
- سؤال DNS عن الـ IP بتاع الدومين (من 30 لـ 80 مللي ثانية)
- فتح TCP connection بـ handshake = round trip كامل (من 50 لـ 150 مللي ثانية على 4G)
- عمل TLS handshake لو الموقع HTTPS = round trip أو اتنين زيادة (من 100 لـ 250 مللي ثانية)
الإجمالي: من 180 لـ 480 مللي ثانية ضايعة لكل دومين خارجي بشكل منفصل. ولو عندك 3 دومينات (fonts، analytics، CDN صور)، الضريبة بتتضرب 3.
قبل التعريف العلمي: مثال مطعم الديليفري
تخيل إنك رايح مطعم delivery تاخد طلبك. عندك سيناريوهين:
السيناريو الأول (بدون Resource Hints): توصل المطعم على غفلة. الويتر يلاقيلك ترابيزة، تقعد، تقرأ المنيو، تأكد البيانات بتاعتك، الكاشير يحضّر الفاتورة، الشيف يبتدي يطبخ. كل خطوة بياخد دقيقة. الأكل وصلك بعد 8 دقايق.
السيناريو الثاني (مع Resource Hints): اتصلت قبل ما تخرج من البيت بـ 10 دقايق وقلت "أنا جاي وعايز كذا". لما وصلت، الترابيزة جاهزة، الفاتورة محضّرة، الأكل في الفرن. أكلت بعد دقيقتين.
المطعم في المثال ده هو الدومين الخارجي. والمكالمة قبل الخروج هي الـ Resource Hint. كل خطوة من خطوات الاستقبال (الترابيزة، الفاتورة، الطلب) هي خطوة من خطوات إعداد الاتصال (DNS، TCP، TLS).
التعريف العلمي
Resource Hints هي مجموعة من قيم الـ rel لتاج <link>، اتعرّفت رسميًا في HTML Living Standard ومواصفة W3C Resource Hints. هي 4 أنواع، كل واحدة بتشتغل على طبقة مختلفة:
- dns-prefetch: يقول للمتصفح "اعمل DNS lookup للدومين ده دلوقتي". أرخص حاجة. بيوفر من 30 لـ 80 مللي ثانية.
- preconnect: يعمل DNS + TCP + TLS كلهم مسبقًا. أقوى حاجة. بيوفر من 180 لـ 480 مللي ثانية.
- preload: يقول للمتصفح "حمّل المورد ده دلوقتي بأولوية عالية" حتى لو الـ parser لسه ما وصلش له في الكود. مفيد للخطوط وصور الـ hero.
- prefetch: يحمّل مورد متوقع للصفحة التالية، بأولوية منخفضة جدًا، في وقت فراغ المتصفح. مفيد للـ checkout page بعد ما المستخدم يضيف منتج للسلة.
الحل: 4 سطور تضيفها في <head>
القاعدة الذهبية: ضع كل Resource Hint قبل أي <link rel="stylesheet"> أو <script> ممكن يحتاج الدومين ده.
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>مدوّنتي</title>
<!-- 1. preconnect لدومين الخطوط (مهم حد التأكيد) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 2. dns-prefetch لـ analytics (احتمالي) -->
<link rel="dns-prefetch" href="https://api.analytics.example.com">
<!-- 3. preload للخط والصورة الأساسية -->
<link rel="preload" href="/fonts/cairo-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/images/hero.webp" as="image" fetchpriority="high">
<!-- 4. الـ stylesheet الفعلي بيجي بعد الـ hints -->
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<img src="/images/hero.webp" alt="بانر المدوّنة الرئيسي" />
</body>
</html>أرقام مقاسة على Lighthouse 11
على blog شخصي يستعمل Cairo من Google Fonts و analytics على دومين تالت، تمّ القياس على Pixel 7a متصل بـ 4G في الإسكندرية (RTT حوالي 120 مللي ثانية):
- قبل الإضافة: First Contentful Paint = 2,140 مللي ثانية
- بعد الإضافة: First Contentful Paint = 1,420 مللي ثانية
- التوفير الفعلي: 720 مللي ثانية (تحسّن بنسبة 33%)
- Largest Contentful Paint اتحسّن من 3,180ms لـ 2,240ms
الأرقام دي متوافقة مع تقارير Web.dev و Chrome User Experience Report لمواقع تستعمل Google Fonts بدون preconnect.
الفرق بين preconnect و dns-prefetch — متى تختار إيه
الناس بتلخبط بينهم. القاعدة البسيطة:
- preconnect: استخدمه لو متأكد 95% إن مورد من الدومين ده هيتطلب فعلًا (الخطوط، الـ CDN الرئيسي للصور). كلفته مش مجانية لأن الـ TCP+TLS connection بيفضل مفتوح حتى لو ما اتستخدمش.
- dns-prefetch: استخدمه لدومينات احتمالية (analytics ممكن المستخدم يقفل tab قبل ما يتحمّل، أو widget social ممكن ما يظهرش لكل المستخدمين).
الحد الآمن: من 4 لـ 6 preconnect في الصفحة الواحدة. أكتر من كده بيستهلك ذاكرة المتصفح وممكن يضر الأداء على الموبايلات الضعيفة، كما وثّق فريق Chrome في 2023.
4 Trade-offs لازم تعرفها قبل ما تنشر
- preconnect بياخد bandwidth وذاكرة: كل connection مفتوح بياكل حوالي 5 كيلوبايت من ذاكرة المتصفح. على موبايل بـ 2 جيجا RAM، 10 preconnect ممكن يبدأوا يأذوا.
- preload ممكن يأذي بدل ما يساعد: لو preload-ت مورد مش critical فعلًا (زي صورة في footer)، هتأخر الموارد المهمة لأن المتصفح هيدّيه أولوية.
- crossorigin attribute مهم جدًا للخطوط: لو نسيت كلمة
crossoriginمع preconnect لـ fonts.gstatic.com، المتصفح هيفتح connection بدون credentials، وبعدين يفتح connection تاني للخط الفعلي. كل التوفير يضيع. - prefetch مش مضمون: المتصفح حر يتجاهله لو الشبكة بطيئة، البطارية واطية، أو الـ Data Saver mode شغّال. متعتمدش عليه في موارد critical.
متى لا تستخدم Resource Hints
- لو كل مواردك على نفس الدومين الرئيسي، preconnect مش هيفيد لأن الـ connection مفتوح أصلًا من تحميل الـ HTML.
- لو موقعك صفحة واحدة بسيطة بحجم أقل من 100 كيلوبايت، التحسين هيبقى أقل من 50 مللي ثانية — مش يستاهل التعقيد.
- لو عندك Service Worker بيعمل cache offline، الزيارات الراجعة هتاخد مللي ثواني معدودة، فالـ hints ما هيظهرش فرقها.
- لو على HTTP/3 (QUIC) مع 0-RTT والـ session resumption شغّالة، المكسب من preconnect بيقل لـ 50ms أو أقل.
طريقة التحقق إن الـ Hints بتشتغل فعلًا
- افتح Chrome DevTools واختار Network tab
- اعمل Hard Refresh (
Ctrl+Shift+RأوCmd+Shift+R) - دوّر على أول طلب لدومين الخط (مثلًا cairo.woff2)
- في تفاصيل الطلب، لازم تلاقي Initial Connection time = 0 مللي ثانية أو قريب جدًا منه
لو لسه شايف زمن DNS أو TCP أكتر من صفر مللي ثانية، يبقى الـ hint مش شغّال. الأسباب الأكثر شيوعًا: URL مكتوب غلط بـ www زيادة، أو نسيت crossorigin مع الخطوط، أو الـ hint اتحط بعد <link rel="stylesheet"> اللي محتاجه.
الخطوة التالية
افتح صفحتك الرئيسية، شغّل Lighthouse في Chrome DevTools (Tab اسمه Lighthouse، اختار "Performance" و "Mobile"). شوف قسم "Opportunities". لو لقيت "Preconnect to required origins" أو "Preload key requests" يبقى عندك مكسب جاهز ينطّ. ضيف 2 أو 3 سطور preconnect للدومينات الخارجية اللي بتظهر هناك، وأعد القياس بعد كل تعديل علشان تتأكد إن المتصفح فعلًا بيستخدمها.
المصادر
- HTML Living Standard — Link types: preconnect, preload, prefetch, dns-prefetch (whatwg.org)
- W3C Resource Hints Working Draft (w3.org/TR/resource-hints)
- Web.dev — "Establish network connections early to improve perceived page speed" (2023)
- MDN Web Docs — <link> reference, rel attribute values
- Chrome Developers Blog — "Speed up your site with preconnect" (developer.chrome.com)
- Lighthouse 11.0 audit documentation — "uses-rel-preconnect" و "uses-rel-preload"
- HTTP Archive Web Almanac 2024 — Performance chapter
- RFC 7540 (HTTP/2) و RFC 9114 (HTTP/3) — connection establishment overhead