إنّ جلب الموارد عبر الشبكة بطيء ومكلف:
- تتطلّب الردود الكبيرة العديد من عمليات النقل بين المتصفّح والخادم.
- لن يتم تحميل صفحتك إلى أن يتم تنزيل جميع مواردها المهمة بالكامل.
- إذا كان أحد الأشخاص يصل إلى موقعك الإلكتروني باستخدام خطة بيانات محدودة على شبكة الجوّال، فإنّ كل طلب غير ضروري للشبكة يشكّل هدرًا لأمواله.
كيف يمكنك تجنُّب الطلبات غير الضرورية من الشبكة؟ ذاكرة التخزين المؤقت لبروتوكول HTTP في المتصفّح هي خط الدفاع الأول. لا يُعدّ هذا النهج هو الأكثر فعالية أو مرونة، ولا يمكنك التحكّم بشكل كامل في مدة صلاحية الردود المخزّنة مؤقتًا، ولكنه فعّال ومتوافق مع جميع المتصفّحات ولا يتطلّب الكثير من العمل.
يوضّح لك هذا الدليل أساسيات تنفيذ ذاكرة التخزين المؤقت لبروتوكول HTTP الفعّال.
توافُق المتصفح
لا تتوفّر واجهة برمجة تطبيقات واحدة تُسمى "ذاكرة التخزين المؤقت لبروتوكول HTTP". وهو الاسم العام لمجموعة من واجهات برمجة تطبيقات منصة الويب. تتوفّر واجهات برمجة التطبيقات هذه في جميع المتصفّحات:
Cache-Control
ETag
Last-Modified
آلية عمل ذاكرة التخزين المؤقت على الويب
يتم توجيه جميع طلبات HTTP التي يقدّمها المتصفّح أولاً إلى ذاكرة التخزين المؤقت للمتصفّح للتحقّق مما إذا كانت هناك استجابة صالحة في ذاكرة التخزين المؤقت يمكن استخدامها لتلبية الطلب. وفي حال تطابق الطلب مع أحد الطلبات السابقة، تتم قراءة الردّ من ذاكرة التخزين المؤقت، ما يزيل وقت استجابة الشبكة وتكاليف البيانات التي يتكبّدها النقل.
يتم التحكّم في سلوك ذاكرة التخزين المؤقت لبروتوكول HTTP من خلال مجموعة من عناوين الطلبات وعناوين الاستجابات. في السيناريو المثالي، ستتمكّن من التحكّم في كلّ من رمز تطبيق الويب (الذي سيحدّد رؤوس الطلبات) وإعدادات خادم الويب (التي ستحدّد رؤوس الاستجابات).
يمكنك الرجوع إلى مقالة تخزين HTTP في MDN للحصول على نظرة عامة أكثر تفصيلاً على المفاهيم.
عناوين الطلبات: يجب استخدام الإعدادات التلقائية (عادةً)
هناك عدد من الرؤوس المهمة التي يجب تضمينها في طلبات تطبيق الويب الصادرة، ولكن المتصفّح يعتني دائمًا تقريبًا بإعدادها نيابةً عنك عند إرسال الطلبات. تظهر رؤوس الطلبات التي تؤثّر في التحقّق من مدى حداثة البيانات، مثل If-None-Match
وIf-Modified-Since
، استنادًا إلى فهم المتصفّح للقيم الحالية في ذاكرة التخزين المؤقت لبروتوكول HTTP.
هذه أخبار سارّة، إذ يعني ذلك أنّه يمكنك مواصلة تضمين علامات مثل <img src="my-image.png">
في صفحات HTML، وسيتولى المتصفّح تلقائيًا ميزة التخزين المؤقت لبروتوكول HTTP نيابةً عنك، بدون أي جهد إضافي.
رؤوس الاستجابة: ضبط خادم الويب
إنّ الجزء الأكثر أهمية في إعداد ذاكرة التخزين المؤقت لبروتوكول HTTP هو الرؤوس التي يضيفها خادم الويب إلى كل استجابة خارجية. تساهم جميع الرؤوس التالية في سلوك التخزين المؤقت الفعّال:
Cache-Control
: يمكن أن يعرض الخادم توجيهCache-Control
لتحديد كيفية تخزين المتصفّح وذاكرات التخزين المؤقت الوسيطة الأخرى للاستجابة الفردية ومدة تخزينها.ETag
: عندما يعثر المتصفّح على استجابة مخزّنة مؤقتًا وانتهت صلاحيتها، يمكنه إرسال رمز مميّز صغير (عادةً تجزئة لمحتوى الملف) إلى الخادم للتحقّق مما إذا كان الملف قد تغيّر. إذا أرجع الخادم الرمز المميّز نفسه، يعني ذلك أنّ الملف هو نفسه، ولا حاجة إلى إعادة تنزيله.Last-Modified
: يخدم هذا العنوان الغرض نفسه الذي يخدمهETag
، ولكنه يستخدم استراتيجية مستندة إلى الوقت لتحديد ما إذا كان قد تم تغيير أحد الموارد، على عكس الاستراتيجية المستندة إلى المحتوى فيETag
.
تتضمّن بعض خوادم الويب ميزة مدمجة لضبط هذه الرؤوس تلقائيًا، بينما تترك خوادم أخرى الرؤوس خارج نطاق الإعدادات ما لم يتم ضبطها صراحةً. تختلف التفاصيل المحدّدة لطريقة ضبط الرؤوس اختلافًا كبيرًا استنادًا إلى خادم الويب الذي تستخدمه، ويجب الرجوع إلى مستندات الخادم للحصول على التفاصيل الأكثر دقة.
لتوفير بعض الوقت عليك، إليك تعليمات حول ضبط بعض خوادم الويب الشائعة:
لا يؤدي حذف عنوان الاستجابة Cache-Control
إلى إيقاف ميزة التخزين المؤقت لبروتوكول HTTP. بدلاً من ذلك، تخمن المتصفّحات بفعالية نوع سلوك التخزين المؤقت الأكثر منطقية لنوع معيّن من المحتوى. من المرجّح أنك تريد التحكّم بشكل أكبر من ذلك، لذا ننصحك بأخذ الوقت الكافي لضبط رؤوس الردود.
ما هي قيم رؤوس الاستجابة التي يجب استخدامها؟
هناك سيناريوهان مهمّان يجب مراعاتهما عند ضبط رؤوس استجابة خادم الويب.
التخزين المؤقّت الطويل لعناوين URL التي تتضمّن نُسخًا
لنفترض أنّ خادمك يوجّه المتصفّحات إلى تخزين ملف CSS مؤقتًا لمدة عام واحد (Cache-Control: max-age=31536000
)، ولكنّ المصمّم أجرى للتو تعديلًا عاجلاً عليك نشره على الفور. كيف يتم إشعار المتصفّحات بتعديل النسخة المخزّنة مؤقتًا "القديمة" من الملف؟ لا يمكنك ذلك، على الأقل بدون تغيير عنوان URL للمورد.
بعد أن يخزّن المتصفّح الاستجابة، يتم استخدام النسخة المخزّنة مؤقتًا إلى أن تصبح غير حديثة، كما تحدّد ذلك max-age
أو expires
، أو إلى أن يتمّ إزالتها من ذاكرة التخزين المؤقت لسبب آخر، مثل أن يُمحو المستخدم ذاكرة التخزين المؤقت للمتصفّح. نتيجةً لذلك، قد يستخدم مستخدمون مختلفون إصدارات مختلفة من الملف عند إنشاء الصفحة: يستخدم المستخدمون الذين جلبوا المورد للتو الإصدار الجديد، بينما يستخدم المستخدمون الذين خزّنوا نسخة سابقة (لكنها لا تزال صالحة) إصدارًا قديمًا من استجابة المورد.
كيف يمكنك الاستفادة من مزايا كل من التخزين المؤقت من جهة العميل والتحديثات السريعة؟ يمكنك تغيير عنوان URL للمورد وإجبار المستخدم على تنزيل الردّ الجديد كلما تغيّر محتواه. ويمكنك عادةً إجراء ذلك من خلال تضمين بصمة الملف أو رقم إصداره في اسم الملف، على سبيل المثال style.x234dff.css
.
عند الردّ على طلبات عناوين URL التي تحتوي على "بصمة رقمية" أو معلومات عن الإصدارات، والتي لا يُفترض أن تتغيّر محتوياتها أبدًا، أضِف Cache-Control: max-age=31536000
إلى ردودك.
يؤدي ضبط هذه القيمة إلى إخبار المتصفّح بأنّه عندما يحتاج إلى تحميل عنوان URL نفسه في أي وقت خلال العام التالي (31,536,000 ثانية، وهي الحد الأقصى للقيمة المسموح بها)، يمكنه استخدام القيمة على الفور في ذاكرة التخزين المؤقت لبروتوكول HTTP، بدون الحاجة إلى إرسال طلب شبكة إلى خادم الويب على الإطلاق. هذا رائع، لقد حصلت على الفور على الموثوقية والسرعة الناتجة عن تجنُّب الشبكة.
يمكن لأدوات إنشاء مثل webpack أتمتة عملية منح علامات مرجعية للتشفير لعناوين URL الخاصة بمواد العرض.
إعادة التحقّق من الخادم لعناوين URL غير المحدَّدة الإصدار
لا تتضمّن بعض عناوين URL التي تحمّلها إصدارات. قد لا تتمكّن من تضمين خطوة إنشاء قبل نشر تطبيق الويب، لذا لا يمكنك إضافة تجزئات إلى عناوين URL لملفات الأصول. ويحتاج كل تطبيق ويب إلى ملفات HTML، ولن تتضمّن هذه الملفات (تقريبًا) معلومات عن الإصدارات، لأنّه لن يهتم أحد باستخدام تطبيق الويب إذا كان عليه تذكُّر أنّ عنوان URL المطلوب الانتقال إليه هو https://example.com/index.34def12.html
. ما الذي يمكنك فعله بشأن عناوين URL هذه؟
هذا هو أحد السيناريوهات التي يجب فيها الاعتراف بالهزيمة. لا تكون ذاكرة التخزين المؤقت لبروتوكول HTTP وحدها فعّالة بما يكفي لتجنّب الاتصال بالشبكة تمامًا. (لا داعي للقلق، ستتعرّف قريبًا على خدمة workers التي ستوفّر الدعم الذي نحتاجه لقلب الموازين لصالحك). ولكن هناك بعض الخطوات التي يمكنك اتّخاذها للتأكّد من أنّ طلبات الشبكة سريعة وفعّالة قدر الإمكان.
يمكن أن تساعدك قيم Cache-Control
التالية في ضبط مكان تخزين عناوين URL غير المحدَّدة الإصدار وطريقة تخزينها:
no-cache
. يُطلب من المتصفّح إعادة التحقّق من صحة البيانات مع الخادم في كل مرة قبل استخدام نسخة من عنوان URL محفوظة مؤقتًا.no-store
. يوجّه هذا الإجراء المتصفّح وذاكرات التخزين المؤقت الوسيطة الأخرى (مثل خدمات CDN) إلى عدم تخزين أي إصدار من الملف مطلقًا.private
. يمكن للمتصفّحات تخزين الملف مؤقتًا، ولكن لا يمكن لمخازن التخزين المؤقت الوسيطة فعل ذلك.public
. يمكن تخزين الاستجابة من خلال أي ذاكرة تخزين مؤقت.
اطّلِع على الملحق: مخطّط تدفق Cache-Control
لعرض عملية تحديد قيم Cache-Control
التي يجب استخدامها. يمكن أن يقبل Cache-Control
أيضًا قائمة توجيهات مفصولة بفواصل. راجِع الملحق: أمثلة على Cache-Control
.
يمكن أن يساعدك أيضًا ضبط ETag
أو Last-Modified
. كما هو موضّح في عناوين الاستجابة، يخدم كلا العنوانَين ETag
وLast-Modified
الغرض نفسه: تحديد ما إذا كان المتصفّح بحاجة إلى إعادة تنزيل ملف محفوظ مؤقتًا انتهت صلاحيته. ننصح باستخدام ETag
لأنّه أكثر دقة.
لنفترض أنّه مرّت 120 ثانية على عملية الجلب الأولية وأنّ المتصفّح قد بدأ طلبًا جديدًا للمورد نفسه. أولاً، يتحقّق المتصفّح من ذاكرة التخزين المؤقت لبروتوكول HTTP ويبحث عن الاستجابة السابقة. لا يمكن للمتصفّح استخدام الاستجابة السابقة لأنّها انتهت صلاحيتها الآن. في هذه المرحلة، يمكن للمتصفّح إرسال طلب جديد واسترداد الردّ الكامل الجديد. ومع ذلك، هذا الإجراء غير فعّال لأنّه إذا لم يتغيّر المرجع، ما مِن سبب لتنزيل المعلومات نفسها المتوفّرة في ذاكرة التخزين المؤقت.
هذه هي المشكلة التي تم تصميم الرموز المميّزة للتحقق من الصحة لحلّها، كما هو محدّد في عنوان ETag
. ينشئ الخادم رمزًا عشوائيًا ويعرضه، ويكون عادةً عبارة عن تجزئة أو بصمة أخرى لمحتوى الملف. لا يحتاج المتصفّح إلى معرفة كيفية إنشاء بصمة الجهاز، بل عليه فقط إرسالها إلى الخادم في الطلب التالي. إذا ظلّت البصمة كما هي، يعني ذلك أنّ المورد لم يتغيّر ويمكن للمتصفّح تخطّي عملية التنزيل.
يؤدي ضبط القيمة ETag
أو Last-Modified
إلى تحسين طلب إعادة التحقّق بشكلٍ كبير من خلال السماح له بتشغيل رؤوس الطلب If-Modified-Since
أو If-None-Match
المذكورة في رؤوس الطلبات.
عندما يرصد خادم ويب تم ضبطه بشكل صحيح رؤوس الطلبات الواردة هذه، يمكنه التأكّد مما إذا كان إصدار المورد الذي يتوفّر لدى المتصفّح في ذاكرة التخزين المؤقت لبروتوكول HTTP يتطابق مع أحدث إصدار على خادم الويب. في حال تطابق القيمة، يمكن للخادم الردّ باستجابة HTTP من النوع 304 Not Modified
، ما يعادل "يمكن مواصلة استخدام الإصدار الحالي". لا تتوفّر سوى بيانات قليلة جدًا لنقلها عند إرسال هذا النوع من الردود، لذا يكون عادةً أسرع بكثير من الحاجة إلى إعادة إرسال نسخة من المرجع الفعلي المطلوب.

/file
من الخادم ويُدرِج رأس If-None-Match
لتوجيه الخادم إلى عرض الملف الكامل فقط إذا لم تتطابق قيمة ETag
للملف على الخادم مع قيمة If-None-Match
للمتصفّح. في هذه الحالة، تطابقت القيمتَان، لذا يعرض الخادم استجابة 304 Not Modified
تتضمّن تعليمات حول المدة التي يجب أن يبقى فيها الملف في ذاكرة التخزين المؤقت (Cache-Control: max-age=120
).
ملخّص
تُعدّ ذاكرة التخزين المؤقت لبروتوكول HTTP طريقة فعّالة لتحسين أداء التحميل لأنّها تقلّل من طلبات الشبكة غير الضرورية. وهو متوافق مع جميع المتصفحات ولا يتطلّب الكثير من الجهد لإعداده.
في ما يلي إعدادات Cache-Control
التالية التي تشكل بداية جيدة:
-
Cache-Control: no-cache
للموارد التي يجب إعادة التحقّق من صحتها مع الخادم قبل كل استخدام -
Cache-Control: no-store
للموارد التي لا يجب الاحتفاظ بذاكرة تخزين مؤقتة لها مطلقًا -
Cache-Control: max-age=31536000
للموارد التي تتضمّن إصدارات
ويمكن أن يساعدك العنوان ETag
أو Last-Modified
في إعادة التحقّق من صحة موارد ذاكرة التخزين المؤقت المنتهية الصلاحية بفعالية أكبر.
مزيد من المعلومات
إذا كنت تريد الاطّلاع على مزيد من المعلومات عن استخدام عنوان Cache-Control
، يمكنك الاطّلاع على دليل أفضل ممارسات التخزين المؤقت والمشاكل المتعلّقة بمدة الصلاحية القصوى الذي كتبه "جاك أرشيبالد".
اطّلِع على المقالة الاستفادة من ذاكرة التخزين المؤقت للحصول على إرشادات حول كيفية تحسين استخدام ذاكرة التخزين المؤقت للزوّار المتكرّرين.
الملحق: مزيد من النصائح
إذا كان لديك المزيد من الوقت، إليك طرق إضافية يمكنك من خلالها تحسين استخدام ذاكرة التخزين المؤقت على HTTP:
- استخدِم عناوين URL متسقة. إذا كنت تعرض المحتوى نفسه على عناوين URL مختلفة، سيتم جلب هذا المحتوى وتخزينه عدة مرات.
- الحدّ من إيقاف الاستخدام إذا كان جزء من المورد (مثل ملف CSS) يتم تعديله بشكل متكرّر، في حين أنّ بقية الملف لا يتم تعديلها (مثل رمز المكتبة)، ننصحك بتقسيم الرمز الذي يتم تعديله بشكل متكرّر إلى ملف منفصل واستخدام استراتيجية تخزين مؤقت قصير المدة للرمز الذي يتم تعديله بشكل متكرّر واستراتيجية تخزين مؤقت طويل المدة للرمز الذي لا يتم تغييره كثيرًا.
- اطّلِع على إرشادات
stale-while-revalidate
الجديدة إذا كانت درجة من عدم التحديث مقبولة في سياسةCache-Control
.
الملحق: مخطّط انسيابي لـ Cache-Control

Cache-Control
.
الملحق: Cache-Control
من الأمثلة
قيمة Cache-Control |
الشرح |
---|---|
max-age=86400 |
يمكن أن تخزّن المتصفّحات وذاكرات التخزين المؤقت الوسيطة الردّ مؤقتًا لمدة تصل إلى يوم واحد (60 ثانية × 60 دقيقة × 24 ساعة). |
private, max-age=600 |
يمكن للمتصفح تخزين الاستجابة مؤقتًا (وليس في ذاكرة التخزين المؤقت الوسيطة) لمدة تصل إلى 10 دقائق (60 ثانية × 10 دقائق). |
public, max-age=31536000 |
يمكن تخزين الاستجابة في أي ذاكرة تخزين مؤقت لمدة عام واحد. |
no-store |
لا يُسمح بتخزين الردّ مؤقتًا في ذاكرة التخزين المؤقت، ويجب استرجاعه بالكامل عند كل طلب. |