التخزين المؤقت للأسلوب. أساسيات التخزين المؤقت للعميل بكلمات وأمثلة واضحة. آخر تعديل، Etag، انتهاء الصلاحية، التحكم في ذاكرة التخزين المؤقت: الحد الأقصى للعمر والرؤوس الأخرى. بصمة URL

💖 هل يعجبك؟شارك الرابط مع أصدقائك

يوفر التخزين المؤقت الذي تم تكوينه بشكل صحيح فوائد هائلة في الأداء، ويوفر النطاق الترددي ويقلل تكاليف الخادم، ولكن العديد من المواقع تنفذ التخزين المؤقت بشكل سيئ، مما يؤدي إلى إنشاء حالة سباق تؤدي إلى عدم مزامنة الموارد المترابطة.

تنقسم الغالبية العظمى من أفضل ممارسات التخزين المؤقت إلى أحد النمطين:

النموذج رقم 1: المحتوى غير القابل للتغيير وذاكرة التخزين المؤقت الطويلة ذات الحد الأقصى للتحكم في ذاكرة التخزين المؤقت: الحد الأقصى للعمر = 31536000
  • لا يتغير محتوى عنوان URL، وبالتالي...
  • يمكن للمتصفح أو CDN تخزين المورد بسهولة لمدة عام
  • يمكن استخدام المحتوى المخبأ الأصغر من الحد الأقصى المحدد دون استشارة الخادم

الصفحة: مرحبًا، أحتاج إلى "/script-v1.js" و"/styles-v1.css" و"/cats-v1.jpg" 10:24

كاش: أنا فارغ، ماذا عنك أيها الخادم؟ 10:24

الخادم: حسنًا، ها هما هنا. بالمناسبة، كاش، يجب استخدامها لمدة عام، لا أكثر. 10:25

كاش : شكرا لك! 10:25

الصفحة: مرحى! 10:25

اليوم المقبل

الصفحة: مرحبًا، أحتاج إلى "/script-v2 .js" و"/styles-v2 .css" و"/cats-v1.jpg" 08:14

كاش: هناك صورة مع القطط، ولكن ليس الباقي. الخادم؟ 08:14

الخادم: سهل - إليك CSS & JS الجديدان. مرة أخرى، Cash: مدة صلاحيتها لا تزيد عن عام. 08:15

كاش: عظيم! 08:15

الصفحة: شكرا لك! 08:15

نقدًا: حسنًا، لم أستخدم "/script-v1.js" و"/styles-v1.css" منذ فترة طويلة. حان الوقت لإزالتها. 12:32

باستخدام هذا النمط، لن تقوم أبدًا بتغيير محتوى عنوان URL محدد، بل يمكنك تغيير عنوان URL نفسه:

يحتوي كل عنوان URL على شيء يتغير مع المحتوى. يمكن أن يكون هذا رقم إصدار، أو تاريخًا معدلاً، أو تجزئة محتوى (وهو ما اخترته لمدونتي).

تحتوي معظم الأطر من جانب الخادم على أدوات تتيح لك القيام بأشياء مثل هذه بسهولة (في Django أستخدم Manifest​Static​Files​Storage)؛ هناك أيضًا مكتبات صغيرة جدًا في Node.js تحل نفس المشكلات، على سبيل المثال، gulp-rev.

ومع ذلك، فإن هذا النمط غير مناسب لأشياء مثل المقالات ومنشورات المدونات. لا يمكن إصدار عناوين URL الخاصة بها وقد يتغير محتواها. على محمل الجد، غالبًا ما أواجه أخطاء نحوية وأخطاء في علامات الترقيم وأحتاج إلى أن أكون قادرًا على تحديث المحتوى بسرعة.

النمط رقم 2: محتوى قابل للتغيير يتم التحقق من صحته دائمًا على التحكم في ذاكرة التخزين المؤقت للخادم: no-cache
  • سيتغير محتوى عنوان URL، مما يعني...
  • لا يمكن استخدام أي إصدار مخبأ محليًا دون تحديد الخادم.

الصفحة: مرحبًا، أحتاج إلى محتويات "/about/" و"/sw.js" 11:32

كاش: لا أستطيع مساعدتك. الخادم؟ 11:32

الخادم: هناك بعض. النقدية، احتفظ بها معك، لكن اسألني قبل استخدامها. 11:33

كاش: بالضبط! 11:33

الصفحة: شكرا لك! 11:33

اليوم المقبل

الصفحة: مرحبًا، أحتاج إلى محتويات "/about/" و"/sw.js" مرة أخرى 09:46

كاش: دقيقة واحدة فقط. الخادم، هل نسختي بخير؟ نسخة "/about/" من يوم الاثنين، و"/sw.js" من الأمس. 09:46

الخادم: "/sw.js" لم يتغير... 09:47

النقدية: بارد. الصفحة، احتفظ بـ "/sw.js" . 09:47

الخادم: ...ولكن لدي "/حول/" نسخة جديدة. احتفظ بالنقود، لكن مثل المرة السابقة، لا تنس أن تسألني أولاً. 09:47

كاش: فهمت! 09:47

الصفحة: عظيم! 09:47

ملاحظة: عدم وجود ذاكرة تخزين مؤقت لا تعني "عدم تخزين ذاكرة التخزين المؤقت"، بل تعني "التحقق" (أو إعادة التحقق من صحة) المورد المخزن مؤقتًا على الخادم. ويخبر no-store المتصفح بعدم التخزين المؤقت على الإطلاق. كما أن "ضرورة إعادة التحقق" لا تعني إعادة التحقق الإلزامية، ولكن يتم استخدام المورد المخزن مؤقتًا فقط إذا كان أصغر من الحد الأقصى المحدد، وإلا فسيتم إعادة التحقق منه. هذه هي الطريقة التي بدأ بها كل شيء الكلمات الدالةللتخزين المؤقت.

في هذا النمط، يمكننا إضافة ETag (معرف الإصدار الذي تختاره) أو رأس آخر تعديل للاستجابة. في المرة التالية التي يطلب فيها العميل المحتوى، يتم إخراج If-None-Match أو If-Modified-Since، على التوالي، مما يسمح للخادم بأن يقول "استخدم ما لديك، ذاكرة التخزين المؤقت الخاصة بك محدثة"، أي إرجاع HTTP 304.

إذا كان إرسال ETag / Last-Modified غير ممكن، فسيقوم الخادم دائمًا بإرسال المحتوى بالكامل.

يتطلب هذا النمط دائمًا مكالمات الشبكة، لذا فهو ليس بجودة النمط الأول، والذي يمكنه الاستغناء عن طلبات الشبكة.

ليس من غير المألوف أننا لا نملك البنية التحتية للنمط الأول، ولكن قد تنشأ أيضًا مشاكل في طلبات الشبكة في النمط 2 نتيجة لذلك، يتم استخدام خيار وسيط: الحد الأقصى للعمر القصير والمحتوى القابل للتغيير. هذه تسوية سيئة.

يعد استخدام الحد الأقصى للعمر مع محتوى قابل للتغيير خيارًا خاطئًا بشكل عام

وللأسف، من الشائع صفحات جيثب؛

يتصور:

  • /شرط/
  • /styles.css
  • /script.js

مع رأس الخادم:

التحكم في ذاكرة التخزين المؤقت: يجب إعادة التحقق، الحد الأقصى للعمر = 600

  • تغييرات محتوى URL
  • إذا كان لدى المتصفح نسخة مخبأة أحدث من 10 دقائق، فسيتم استخدامها دون استشارة الخادم
  • إذا لم يكن هناك مثل هذا التخزين المؤقت، فسيتم استخدام طلب الشبكة، إن أمكن باستخدام If-Modified-Since أو If-None-Match

الصفحة: مرحبًا، أحتاج إلى "/article/" و"/script.js" و"/styles.css" 10:21

كاش: ليس لدي شيء مثلك أيها الخادم؟ 10:21

الخادم: لا مشكلة، ها هما هنا. لكن تذكر، النقد: يمكن استخدامها خلال الدقائق العشر القادمة. 10:22

كاش: نعم! 10:22

الصفحة: شكرا لك! 10:22

الصفحة: مرحبًا، أحتاج إلى "/article/" و"/script.js" و"/styles.css" مرة أخرى 10:28

كاش: عفوًا، أنا آسف، لكنني فقدت "/styles.css"، ولكن لدي كل شيء آخر، تفضل. الخادم، هل يمكنك تخصيص "/styles.css" لي؟ 10:28

الخادم: حسنًا، لقد تغير بالفعل منذ آخر مرة أخذته فيها. يمكنك استخدامه بأمان لمدة 10 دقائق القادمة. 10:29

كاش: لا مشكلة. 10:29

الصفحة: شكرا لك! ولكن يبدو أن هناك خطأ ما! يتم تقسيم كل شيء! ما الذي يجري؟ 10:29

هذا النمط له الحق في الحياة أثناء الاختبار، لكنه يكسر كل شيء في مشروع حقيقي ومن الصعب جدًا تتبعه. في المثال أعلاه، قام الخادم بتحديث HTML وCSS وJS، ولكن يتم عرض الصفحة باستخدام HTML وJS القديمين المخزنين مؤقتًا، بالإضافة إلى CSS المحدث من الخادم. عدم تطابق الإصدار يفسد كل شيء.

في كثير من الأحيان، عندما نقوم بإجراء تغييرات كبيرة على HTML، نقوم بتغيير كل من CSS ليعكس البنية الجديدة بشكل صحيح وJavaScript لمواكبة المحتوى والتصميم. كل هذه الموارد مستقلة، لكن رؤوس التخزين المؤقت لا يمكنها التعبير عن ذلك. ونتيجة لذلك، قد يجد المستخدمون أنفسهم احدث اصدارواحد/اثنين من الموارد والإصدار القديم من الباقي.

يتم تعيين الحد الأقصى للعمر بالنسبة لوقت الاستجابة، لذلك إذا تم نقل جميع الموارد كجزء من عنوان واحد، فستنتهي صلاحيتها في نفس الوقت، ولكن لا تزال هناك فرصة صغيرة لإلغاء التزامن. إذا كانت لديك صفحات لا تتضمن JavaScript أو تتضمن أنماطًا أخرى، فستكون تواريخ انتهاء صلاحية ذاكرة التخزين المؤقت الخاصة بها غير متزامنة. والأسوأ من ذلك، أن المتصفح يقوم باستمرار بسحب المحتوى من ذاكرة التخزين المؤقت، دون أن يعلم أن HTML وCSS وJS مترابطة، لذلك يمكنه بكل سرور سحب شيء واحد من القائمة ونسيان كل شيء آخر. بالنظر إلى كل هذه العوامل معًا، يجب أن تفهم أن احتمالية وجود إصدارات غير متطابقة مرتفعة جدًا.

بالنسبة للمستخدم، قد تكون النتيجة تخطيط صفحة معطلاً أو مشاكل أخرى. من مواطن الخلل الصغيرة إلى المحتوى غير القابل للاستخدام تمامًا.

ولحسن الحظ، لدى المستخدمين مخرج للطوارئ...

تحديث الصفحة يساعد في بعض الأحيان

إذا تم تحميل الصفحة عن طريق التحديث، فستقوم المتصفحات دائمًا بإجراء عملية إعادة التحقق من جانب الخادم، متجاهلة max-age . لذلك، إذا كان لدى المستخدم شيء معطل بسبب الحد الأقصى للعمر، فيمكن لتحديث بسيط للصفحة إصلاح كل شيء. ولكن، بالطبع، بعد العثور على الملاعق، ستظل الرواسب موجودة وسيكون الموقف تجاه موقعك مختلفا إلى حد ما.

يمكن لعامل الخدمة إطالة عمر هذه الأخطاء

على سبيل المثال، لديك عامل خدمة مثل هذا:

نسخة كونست = "2"؛ self.addEventListener("install", events => (event.waitUntil(caches.open(`static-$(version)`) .then(cache =>ذاكرة التخزين المؤقت.addAll([ "/styles.css", "/script .js" ]))); ))); self.addEventListener("activate"، events => ( // ...حذف ذاكرات التخزين المؤقت القديمة... )); self.addEventListener("fetch", events => (event.respondWith(caches.match(event.request) .then(response => Response || fetch(event.request))); ));

عامل الخدمة هذا:

  • يخزن البرنامج النصي والأنماط
  • يستخدم ذاكرة التخزين المؤقت إذا كان هناك تطابق، وإلا فإنه يصل إلى الشبكة

إذا قمنا بتغيير CSS/JS، فإننا أيضًا نزيد رقم الإصدار، مما يؤدي إلى التحديث. ومع ذلك، نظرًا لأن addAll يصل إلى ذاكرة التخزين المؤقت أولاً، فيمكننا الدخول في حالة سباق بسبب الحد الأقصى للعمر وإصدارات CSS وJS غير المتطابقة.

بمجرد تخزينها مؤقتًا، سيكون لدينا CSS وJS غير متوافقين حتى التحديث التالي لعامل الخدمة - وذلك ما لم ندخل في حالة سباق مرة أخرى أثناء التحديث.

يمكنك تخطي التخزين المؤقت في عامل الخدمة:

Self.addEventListener("install", events => (event.waitUntil(caches.open(`static-$(version)`) .then(cache =>ذاكرة التخزين المؤقت.addAll([ طلب جديد("/styles.css", (ذاكرة التخزين المؤقت: "no-cache" )))، new Request("/script.js"، (ذاكرة التخزين المؤقت: "no-cache" )) ])));

لسوء الحظ، خيارات التخزين المؤقت غير مدعومة في Chrome/Opera وقد تمت إضافتها للتو إلى الإصدار الليلي من Firefox، ولكن يمكنك القيام بذلك بنفسك:

Self.addEventListener("install", events => (event.waitUntil(caches.open(`static-$(version)`) .then(cache => Promise.all([ "/styles.css", "/script .js" ).map(url => ( // ذاكرة التخزين المؤقت-تمثال نصفي باستخدام سلسلة استعلام عشوائية return fetch(`$(url)?$(Math.random())`).then(response => ( // فشل على 404، 500 وما إلى ذلك إذا (!response.ok) ألقى خطأ ("ليس جيدًا")؛

في هذا المثال، قمت بإعادة تعيين ذاكرة التخزين المؤقت باستخدام رقم عشوائي، ولكن يمكنك المضي قدمًا وإضافة تجزئة للمحتوى عند الإنشاء (وهذا مشابه لما يفعله sw-precache). هذا نوع من تنفيذ النمط الأول مع باستخدام جافا سكريبت، ولكنه يعمل فقط مع عامل الخدمة، وليس المتصفحات وCDN.

يعمل عمال الخدمة وذاكرة التخزين المؤقت لـ HTTP معًا بشكل رائع، فلا تجعلهم يتشاجرون!

كما ترون، يمكنك التغلب على أخطاء التخزين المؤقت في عامل الخدمة لديك، ولكن من الأفضل حل المشكلة الجذرية. الإعداد الصحيحالتخزين المؤقت لا يجعل مهمة عامل الخدمة أسهل فحسب، بل يساعد أيضًا المتصفحات التي لا تدعم عمال الخدمة (Safari، IE/Edge)، ويتيح لك أيضًا تحقيق أقصى استفادة من CDN الخاص بك.

يمكن لرؤوس التخزين المؤقت المناسبة أيضًا أن تجعل تحديث عامل الخدمة أسهل كثيرًا.

نسخة كونست = "23"؛ self.addEventListener("install", events => (event.waitUntil(caches.open(`static-$(version)`) .then(cache =>ذاكرة التخزين المؤقت.addAll([ "/", "/script-f93bca2c. js"، "/styles-a837cb1e.css"، "/cats-0e9a2ef4.jpg" ]))); )));

لقد قمت هنا بتخزين الصفحة الجذر مؤقتًا بالنمط رقم 2 (إعادة التحقق من جانب الخادم) وجميع الموارد الأخرى بالنمط رقم 1 (محتوى غير قابل للتغيير). سيؤدي كل تحديث لعامل الخدمة إلى طلب الصفحة الجذرية، ولن يتم تحميل جميع الموارد الأخرى إلا إذا تغير عنوان URL الخاص بها. يعد هذا أمرًا جيدًا لأنه يوفر حركة المرور ويحسن الأداء، بغض النظر عما إذا كنت تقوم بالترقية من إصدار سابق أم لا نسخة قديمة.

هناك ميزة كبيرة هنا مقارنة بالتنفيذ الأصلي، حيث يتم تنزيل الملف الثنائي بأكمله حتى مع تغيير بسيط أو يؤدي إلى مقارنة ثنائية معقدة. بهذه الطريقة يمكننا تحديث تطبيق ويب كبير بحمل صغير نسبيًا.

يعمل عمال الخدمة بشكل أفضل كتعزيز وليس كعكاز مؤقت، لذا استخدم ذاكرة التخزين المؤقت بدلاً من محاربتها.

عند استخدامها بعناية، يمكن أن يكون الحد الأقصى للعمر والمحتوى المتغير جيدًا جدًا

غالبًا ما يكون الحد الأقصى للعمر هو الاختيار الخاطئ للمحتوى القابل للتغيير، ولكن ليس دائمًا. على سبيل المثال، يبلغ الحد الأقصى لعمر المقالة الأصلية ثلاث دقائق. لا تمثل حالة السباق مشكلة نظرًا لعدم وجود تبعيات على الصفحة باستخدام نفس نمط التخزين المؤقت (تستخدم CSS وJS والصور النمط رقم 1 - محتوى غير قابل للتغيير)، وكل شيء آخر لا يستخدم هذا النمط.

يعني هذا النمط أنه يمكنني بسهولة كتابة مقالة شائعة، ويمكن لـ CDN (Cloudflare) الخاص بي إزالة العبء عن الخادم، طالما أنني على استعداد للانتظار ثلاث دقائق حتى تصبح المقالة المحدثة متاحة للمستخدمين.

يجب استخدام هذا النمط دون تعصب. إذا أضفت قسمًا جديدًا إلى مقالة، وربطته من مقالة أخرى، فقد قمت بإنشاء تبعية يجب حلها. يمكن للمستخدم الضغط على الرابط والحصول على نسخة من المقالة بدون القسم المطلوب. إذا كنت أرغب في تجنب ذلك، فيجب علي تحديث المقالة، وحذف النسخة المخزنة مؤقتًا من المقالة من Cloudflare، والانتظار ثلاث دقائق، وبعد ذلك فقط قم بإضافة الرابط إلى مقالة أخرى. نعم، هذا النمط يتطلب الحذر.

عند استخدامه بشكل صحيح، يوفر التخزين المؤقت تحسينات كبيرة في الأداء وتوفير النطاق الترددي. يمكنك تقديم محتوى غير قابل للتغيير إذا كان بإمكانك تغيير عنوان URL بسهولة، أو استخدام إعادة التحقق من جانب الخادم. امزج الحد الأقصى للعمر والمحتوى القابل للتغيير إذا كنت شجاعًا بما فيه الكفاية وواثقًا من أن المحتوى الخاص بك لا يحتوي على تبعيات يمكن أن تخرج عن المزامنة.

عند إجراء تغييرات على مواقع الويب، غالبًا ما نواجه حقيقة أن محتويات الصفحات وملفات CSS والبرامج النصية (.js) يتم تخزينها مؤقتًا بواسطة المتصفح وتظل دون تغيير لفترة طويلة. يؤدي هذا إلى حقيقة أنه لكي تنعكس التغييرات التي تم إجراؤها في جميع المتصفحات، من الضروري تعويد العملاء على مجموعات معقدة من F5 أو Ctrl + F5. ومن وقت لآخر تأكد من الضغط عليهم.

هذه العملية مملة للغاية وغير مريحة. يمكنك، بالطبع، الخروج من الموقف عن طريق إعادة تسمية الملفات في كل مرة، ولكن مرة أخرى غير مريح.

ومع ذلك، هناك طريقة تسمح لنا بالبقاء بنفس الأسماء وإعادة تعيين التخزين المؤقت لملفات ‎.css أو ‎.js في الوقت الذي نحتاج إليه فيه. وننسى Ctrl + F5 إلى الأبد.

خلاصة القول هي أننا سنقوم بإرفاق معلمة زائفة بملفاتنا .css أو .js في النهاية، والتي سنقوم بتغييرها من وقت لآخر، وبالتالي إعادة تعيين ذاكرة التخزين المؤقت في المتصفح.

وبذلك يكون الدخول في مصدر الرمزسوف تبدو الآن مثل هذا:

حيث 186485 عبارة عن مجموعة عشوائية ستخرج نفس الملف، لكن المتصفح يفسره على أنه جديد، وذلك بفضل المعلمة الزائفة ?186485

الآن، لكي لا نغير جميع تكرارات المعلمة الخاصة بنا في كل مرة، سنقوم بتعيينها في ملف php، والذي سنقوم بتوصيله بجميع الأماكن التي نحتاجها:



أخبر الأصدقاء