ضبط سلوك تخزين HTTP

يوضّح لك هذا الدرس التطبيقي حول الترميز كيفية تغيير عناوين التخزين المؤقت لبروتوكول HTTP التي يعرضها خادم ويب مستند إلى Node.js، والذي يشغّل إطار عمل عرض Express. وسيوضّح أيضًا كيفية التأكّد من أنّه يتم تطبيق سلوك التخزين المؤقت الذي تتوقّعه، باستخدام لوحة "الشبكة" في "أدوات مطوّري البرامج" في Chrome.

التعرّف على نموذج المشروع

في ما يلي الملفات الرئيسية التي ستتعامل معها في نموذج المشروع:

  • يحتوي server.js على رمز Node.js الذي يعرض محتوى التطبيق الإلكتروني. ويستخدم Express لمعالجة طلبات HTTP والاستجابات. على وجه الخصوص، يتم استخدام express.static() لعرض كل الملفات المحلية في الدليل العلني، لذا سيكون serve-static المستند مفيدًا.
  • public/index.html هو رمز HTML لتطبيق الويب. مثل معظم ملفات HTML، لا يحتوي هذا الملف على أي معلومات عن الإصدار كجزء من عنوان URL الخاص به.
  • public/app.15261a07.js وpublic/style.391484cf.css هما مواد عرض JavaScript وCSS لتطبيق الويب. تحتوي كلّ من هذه الملفات على تجزئة في عناوين URL الخاصة بها، تتوافق مع محتواها. تتحمّل index.html مسؤولية متابعة عنوان URL المحدّد الذي يجب تحميله.

ضبط رؤوس التخزين المؤقت لصفحات HTML

عند الردّ على طلبات عناوين URL التي لا تحتوي على معلومات عن الإصدار، احرص على إضافة Cache-Control: no-cache إلى رسائل الردّ. بالإضافة إلى ذلك، ننصحك بضبط أحد عنوانَي الاستجابة الإضافيَين التاليَين: Last-Modified أو ETag. تندرج index.html ضمن هذه الفئة. يمكنك تقسيم ذلك إلى خطوتَين.

أولاً، يتم التحكّم في عنوانَي Last-Modified وETag من خلال خيارَي الضبط etag و lastModified. يتم ضبط كلا الخيارَين تلقائيًا على true لجميع ردود HTTP، لذا في هذا الإعداد الحالي، لست بحاجة إلى تفعيل هذا السلوك. ولكن يمكنك أن تكون صريحًا في الإعدادات على أي حال.

ثانيًا، يجب أن يكون بإمكانك إضافة عنوان Cache-Control: no-cache، ولكن فقط لمستندات HTML (index.html في هذه الحالة). إنّ أسهل طريقة لتحديد هذا العنوان بشكل مشروط هي كتابة setHeaders function مخصّصة، وضمن ذلك، التحقّق ممّا إذا كان الطلب الوافد مخصّصًا لمستند HTML.

  • انقر على Remix to Edit (إنشاء ريمكس لتعديل المحتوى) ليصبح المشروع قابلاً للتعديل.

تبدأ إعدادات العرض الثابت في server.js على النحو التالي:

app.use(express.static('public'));
  • أجرِ التغييرات الموضّحة أعلاه، ومن المفترض أن تحصل على محتوى يشبه ما يلي:
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    }
  },
}));

ضبط رؤوس التخزين المؤقت لعناوين URL التي تتضمّن إصدارات

عند الردّ على طلبات عناوين URL التي تحتوي على "معرف إصبع" أو معلومات عن الإصدارات، والتي لا يُفترض أن تتغيّر محتوياتها أبدًا، أضِف Cache-Control: max-age=31536000 إلى ردودك. تندرج app.15261a07.js و style.391484cf.css ضمن هذه الفئة.

استنادًا إلى الرمز البرمجي setHeaders function المستخدَم في الخطوة الأخيرة، يمكنك إضافة منطق إضافي للتحقّق مما إذا كان طلب معيّنًا يخصّ عنوان URL بإصدار محدّد، وإذا كان الأمر كذلك، أضِف العنوان Cache-Control: max-age=31536000.

إنّ الطريقة الأكثر فعالية لإجراء ذلك هي استخدام تعبير عادي لمعرفة ما إذا كانت مادة العرض المطلوبة تتطابق مع نمط معيّن تعرف أنّه يندرج ضمنه العلامات المجزّأة. في ما يتعلّق بهذا النموذج من المشاريع، يكون دائمًا من ثمانية أحرف من مجموعة الأرقام من 0 إلى 9 والأحرف الصغيرة من a إلى f (أي أحرفالسداسي العشري). يتم دائمًا فصل العلامة الهاشتاغ بحرف . على كلا الجانبَين.

يمكن التعبير عن تعبير عادي يتطابق مع هذه القواعد العامة على النحو التالي: new RegExp('\\.[0-9a-f]{8}\\.').

  • عدِّل الدالة setHeaders لتظهر على النحو التالي:
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');

    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    } else if (hashRegExp.test(path)) {
      // If the RegExp matched, then we have a versioned URL.
      res.setHeader('Cache-Control', 'max-age=31536000');
    }
  },
}));

تأكيد السلوك الجديد باستخدام "أدوات مطوّري البرامج"

بعد إجراء التعديلات على خادم الملفات الثابتة، يمكنك التحقّق من التأكّد من ضبط العناوين الصحيحة من خلال معاينة التطبيق المنشور مع فتح لوحة "الشبكة" في "أدوات مطوّري البرامج".

  • لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق. ثم اضغط على ملء الشاشة ملء الشاشة.

  • يمكنك تخصيص الأعمدة التي يتم عرضها في لوحة "الشبكة" لتضمين المعلومات الأكثر صلةً، وذلك من خلال النقر بزر الماوس الأيمن في عنوان العمود:

ضبط لوحة "الشبكة" في "أدوات مطوّري البرامج"

في ما يلي الأعمدة التي يجب الانتباه إليها: Name وStatus وCache-Control ETag وLast-Modified.

  • مع فتح أدوات المطوّرين في لوحة "الشبكة"، أعِد تحميل الصفحة.

بعد تحميل الصفحة، من المفترض أن تظهر لك إدخالات في لوحة "الشبكة" تبدو على النحو التالي:

أعمدة لوحة الشبكة

الصف الأول مخصّص لمستند HTML الذي انتقلت إليه. يتم تقديم هذا المحتوى بشكلٍ سليم مع Cache-Control: no-cache. حالة استجابة HTTP لهذا الطلب هي 304. وهذا يعني أنّ المتصفّح عرف عدم استخدام ملف HTML المخزّن مؤقتًا على الفور، ولكن بدلاً من ذلك، قدّم طلب HTTP إلى خادم الويب، باستخدام معلومات Last-Modified وETag لمعرفة ما إذا كان هناك أي تعديل على ملف HTML الذي كان لديه في الذاكرة المؤقتة. تشير استجابة HTTP 304 إلى عدم توفّر ملف HTML معدَّل.

الصفان التاليان مخصّصان لمواد عرض JavaScript وCSS ذات الإصدارات المحدّدة. من المفترض أن يتم عرضها باستخدام Cache-Control: max-age=31536000، ورمز حالة HTTP لكل منها هو 200. بسبب الإعدادات المستخدَمة، لا يتم تقديم طلب فعلي إلى خادم Node.js، وسيؤدي النقر على الإدخال إلى عرض تفاصيل إضافية، بما في ذلك أنّ الاستجابة جاءت "(من ذاكرة التخزين المؤقت على القرص)".

حالة استجابة الشبكة هي 200.

لا يهمّ كثيرًا القيم الفعلية لعمودَي ETag وLast-Modified. والشيء المهم هو التأكّد من أنّه يتم ضبطها.

ملخّص

بعد مراجعة الخطوات الواردة في هذا الدرس التطبيقي حول الترميز، أصبحت الآن على دراية بكيفية ضبط رؤوس استجابة HTTP في خادم ويب يستند إلى Node.js باستخدام Express، للاستفادة إلى أقصى حد من ذاكرة التخزين المؤقت لبروتوكول HTTP. تتوفّر لك أيضًا الخطوات التي تحتاجها للتأكّد من استخدام سلوك التخزين المؤقت المتوقّع، وذلك من خلال لوحة "الشبكة" في أدوات مطوّري البرامج في Chrome.