ميزة "التخزين المؤقت للصفحات"

إنّ ميزة "التخزين المؤقت للصفحات" (أو bfcache) هي تحسين في المتصفّح تتيح إمكانية التنقّل الفوري للرجوع إليها أو إعادة توجيهها. يحسن ذلك بشكل كبير تجربة التصفح، خاصة للمستخدمين الذين لديهم شبكات أو أجهزة أبطأ.

توضّح هذه الصفحة كيفية تحسين صفحاتك من أجل استخدام ميزة "التخزين المؤقت للصفحات" في جميع المتصفحات.

توافُق المتصفح

كان bfcache متاحًا في كل من Firefox وSafari لسنوات عديدة على أجهزة الكمبيوتر المكتبي والأجهزة الجوّالة.

بدءًا من الإصدار 86، أتاح Chrome ميزة "التخزين المؤقت للصفحات" للتنقلات عبر المواقع الإلكترونية على نظام التشغيل Android لنسبة صغيرة من المستخدمين. وفي الإصدارات اللاحقة، سيتم طرح المزيد من الميزات تدريجيًا. بدءًا من الإصدار 96، تم تفعيل ميزة "التخزين المؤقت للصفحات" لجميع مستخدمي Chrome على أجهزة الكمبيوتر المكتبي والأجهزة الجوّالة.

أساسيات Bfcache

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

يعرض الفيديو التالي مقدار ميزة "التخزين المؤقت للصفحات" التي يمكن أن تؤدي إلى تسريع عملية التنقّل:

يؤدي استخدام ميزة "التخزين المؤقت للصفحات" إلى تحميل الصفحات بسرعة أكبر أثناء التنقّل للأمام والخلف.

تُظهر بيانات استخدام Chrome أنّ عملية انتقال واحدة من كل 10 عمليات على كمبيوتر مكتبي وعملية واحدة من كل 5 عمليات تنقل على الأجهزة الجوّالة تتم للخلف أو للأمام. لهذا السبب، بإمكان ميزة "التخزين المؤقت للصفحات" توفير قدر كبير من الوقت واستخدام البيانات.

آلية عمل ميزة "ذاكرة التخزين المؤقت"

تختلف "ذاكرة التخزين المؤقت" التي تستخدمها ميزة "التخزين المؤقت للصفحات" عن ذاكرة التخزين المؤقت لبروتوكول HTTP التي تؤدي دورها الخاص في تسريع عمليات الانتقال المتكرّرة. وتُعدّ ميزة "التخزين المؤقت للصفحات" لقطة سريعة للصفحة بأكملها في الذاكرة، بما في ذلك كومة JavaScript، في حين تحتوي ذاكرة التخزين المؤقت لـ HTTP على استجابات الطلبات التي تم إجراؤها مسبقًا فقط. ونظرًا لأنه من النادر جدًا أن تكون جميع الطلبات المطلوبة لتحميل صفحة قابلة للتنفيذ من ذاكرة التخزين المؤقت لبروتوكول HTTP، تكون الزيارات المتكررة باستخدام عمليات استعادة ميزة "التخزين المؤقت للصفحات" أسرع دائمًا مقارنةً بعمليات التنقل الأفضل والمحسّنة باستخدام ميزة "التخزين المؤقت للصفحات".

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

والإجابة عن هذا السؤال هي أنّ المتصفّحات توقِف مؤقتًا أي موقّتات معلّقة أو وعود لم يتم حلها للصفحات التي تم تخزينها مؤقتًا، بما في ذلك جميع المهام المعلَّقة تقريبًا في قوائم انتظار مهام JavaScript، واستئناف مهام المعالجة في حال استعادة الصفحة من ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات".

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

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

ميزة "التخزين المؤقت للصفحات" وتطبيقات الصفحة الواحدة (SPA)

بما أنّ ميزة "bfcache" تعمل مع عمليات التنقّل التي يديرها المتصفّح، لا تتوافق مع "عمليات التنقّل اللينة" داخل تطبيق من صفحة واحدة (SPA). ومع ذلك، لا يزال بإمكان ميزة "التخزين المؤقت للصفحات" المساعدة عند المغادرة والعودة إلى SPA.

واجهات برمجة التطبيقات لمراقبة ذاكرة التخزين المؤقت للصفحات

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

إنّ الحدثَين الأساسيَين المستخدَمين لرصد ميزة "التخزين المؤقت للصفحات" هما حدثا نقل الصفحة pageshow وpagehide، وهما متوافقان مع معظم المتصفّحات.

يتم أيضًا إرسال حدثَي دورة حياة الصفحة، freeze وresume، عند إدخال الصفحات مؤقتًا في ذاكرة التخزين المؤقت أو الخروج منها، كما في بعض الحالات الأخرى، على سبيل المثال، عندما يتم تجميد علامة تبويب في الخلفية لتقليل استخدام وحدة المعالجة المركزية (CPU). ولا يتم دعم هذه الأحداث إلا في المتصفحات المستندة إلى Chromium.

رصد عملية استعادة صفحة من ميزة "التخزين المؤقت للصفحات"

يتم تنشيط حدث pageshow بعد الحدث load مباشرةً عند بدء تحميل الصفحة وفي أي وقت تتم فيه استعادة الصفحة من ميزة "التخزين المؤقت للصفحات". يحتوي الحدث pageshow على السمة persisted، وهي true إذا تمت استعادة الصفحة من bfcache أو false. يمكنك استخدام السمة persisted للتمييز بين عمليات تحميل الصفحات العادية وعمليات استعادة ميزة "التخزين المؤقت للصفحات". مثال:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.');
  } else {
    console.log('This page was loaded normally.');
  }
});

في المتصفّحات التي تتيح استخدام واجهة برمجة التطبيقات لمراحل نشاط الصفحة، يتم تنشيط الحدث resume عند استعادة الصفحات من ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات" (قبل حدث pageshow مباشرةً) وعندما يعيد المستخدِم زيارة علامة تبويب مجمّدة في الخلفية. إذا كنت تريد تعديل حالة صفحة بعد تجميدها (بما في ذلك الصفحات المتوفّرة في ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات")، يمكنك استخدام الحدث resume، ولكن إذا كنت تريد قياس معدل نتائج ميزة "التخزين المؤقت للصفحات" على موقعك الإلكتروني، عليك استخدام الحدث pageshow. وفي بعض الحالات، قد تحتاج إلى استخدام كليهما.

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

رصد عملية إدخال ميزة "التخزين المؤقت للصفحات" في إحدى الصفحات

يتم تنشيط الحدث pagehide إما عند إلغاء تحميل صفحة أو عندما يحاول المتصفّح وضعها في ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات".

يتضمّن حدث "pagehide" أيضًا السمة persisted. إذا كان الملف false، يمكنك التأكّد من أنّ الصفحة ليست على وشك الدخول في ميزة "التخزين المؤقت للصفحات". مع ذلك، إذا كانت قيمة السمة persisted هي true، لا يضمن ذلك أنّه سيتم تخزين الصفحة مؤقتًا. يعني ذلك أنّ المتصفّح intends إلى تخزين الصفحة في ذاكرة التخزين المؤقت، ولكن قد تكون هناك عوامل أخرى تجعل من المستحيل تخزين الصفحة في ذاكرة التخزين المؤقت.

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

وبالمثل، يتم تنشيط حدث freeze مباشرةً بعد الحدث pagehide إذا كانت قيمة persisted هي true، ولكن هذا يعني أن المتصفّح intends فقط إلى تخزين الصفحة في ذاكرة التخزين المؤقت. قد يظل عليه تجاهله لعدد من الأسباب التي سيتم توضيحها لاحقًا.

تحسين صفحاتك لاستخدام ميزة "التخزين المؤقت للصفحات"

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

استخدام pagehide بدلاً من unload

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

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

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

على الأجهزة الجوّالة، يحاول Chrome وSafari تخزين الصفحات مؤقتًا باستخدام أدوات معالجة أحداث unload، لأن عدم موثوقية unload على الأجهزة الجوّالة يقلل من مخاطر تعطُّل التطبيق. يتعامل متصفّح Mobile Firefox مع الصفحات التي تستخدم unload على أنّها غير مؤهَّلة لاستخدام ميزة "التخزين المؤقت للصفحات"، باستثناء نظام التشغيل iOS الذي يتطلب أن تستخدم جميع المتصفحات محرك عرض WebKit، حتى يعمل مثل Safari.

لتحديد ما إذا كان هناك أي JavaScript على صفحاتك يستخدم unload، ننصحك باستخدام تدقيق no-unload-listeners في Lighthouse.

للحصول على معلومات حول خطة Chrome لإيقاف unload نهائيًا، يمكنك الرجوع إلى إيقاف حدث "إلغاء التحميل" نهائيًا.

يمكنك استخدام "سياسة الأذونات" لمنع استخدام معالِجات إلغاء التحميل على إحدى الصفحات.

يمكن أن تضيف بعض النصوص البرمجية والإضافات التابعة لجهات خارجية معالِجات إلغاء التحميل إلى الصفحة، ما يؤدي إلى إبطاء الموقع الإلكتروني من خلال جعله غير مؤهَّل لاستخدام ميزة "التخزين المؤقت للصفحات". ولمنع حدوث ذلك في Chrome 115 والإصدارات الأحدث، يمكنك استخدام سياسة الأذونات.

Permission-Policy: unload()

إضافة أدوات معالجة beforeunload فقط بشكل مشروط

لا يجعل حدث beforeunload صفحاتك غير مؤهَّلة لاستخدام ميزة "التخزين المؤقت للصفحات". ومع ذلك، فهي غير موثوقة، لذا لا ننصح باستخدامها إلا عند الضرورة القصوى.

أحد الأمثلة على حالة استخدام beforeunload هي تحذير المستخدم بأنّ لديه تغييرات لم يتم حفظها، سيفقدها في حال مغادرة الصفحة. في هذه الحالة، ننصحك بإضافة beforeunload مستمعين فقط عندما يكون لدى المستخدم تغييرات لم يتم حفظها، ثم إزالتها على الفور بعد حفظ التغييرات غير المحفوظة، كما في الرمز التالي:

function beforeUnloadListener(event) {
  event.preventDefault();
  return event.returnValue = 'Are you sure you want to exit?';
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  window.addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  window.removeEventListener('beforeunload', beforeUnloadListener);
});

الحدّ من استخدام "Cache-Control: no-store"

Cache-Control: no-store هو عنوان من خوادم الويب يمكن أن يضبط عنوان HTTP على الاستجابات التي توجّه المتصفّح إلى عدم تخزين الاستجابة في أي ذاكرة تخزين مؤقت لبروتوكول HTTP. وهو يُستخدم للموارد التي تحتوي على معلومات حساسة للمستخدم، مثل الصفحات المحمية بمعلومات تسجيل دخول.

على الرغم من أنّ ميزة bfcache ليست ذاكرة تخزين مؤقت لبروتوكول HTTP، كانت المتصفحات قد استبعدت سابقًا صفحات من ميزة "التخزين المؤقت للصفحات" عند ضبط Cache-Control: no-store على مورد الصفحة (وليس على أي مورد فرعي). ويعمل Chrome على تغيير هذا السلوك مع الحفاظ على خصوصية المستخدم، ولكن بشكلٍ تلقائي، لا تكون الصفحات التي تستخدم Cache-Control: no-store مؤهّلة لميزة "التخزين المؤقت للصفحات".

لتحسين ميزة "التخزين المؤقت للصفحات"، استخدِم Cache-Control: no-store فقط على الصفحات التي تحتوي على معلومات حساسة يجب عدم تخزينها مؤقتًا.

بالنسبة إلى الصفحات التي تريد عرض محتوى حديث دائمًا بدون أن تتضمّن معلومات حساسة، استخدِم السمة Cache-Control: no-cache أو السمة Cache-Control: max-age=0. وهي تطلب من المتصفّح إعادة التحقّق من المحتوى قبل عرضه، ولا تؤثر في أهلية استخدام ميزة "التخزين المؤقت للصفحات" في الصفحة لأنّ استعادة الصفحة من ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات" لا تشمل ذاكرة التخزين المؤقت لـ HTTP.

إذا كان المحتوى يتغيّر دقيقة بدقيقة، يمكنك جلب التعديلات باستخدام حدث pageshow بدلاً من ذلك، وذلك لإبقاء صفحتك محدَّثة كما هو موضّح في القسم التالي.

تعديل البيانات القديمة أو الحسّاسة بعد استعادة ميزة "التخزين المؤقت للصفحات"

إذا كان موقعك الإلكتروني يحتفظ ببيانات حالة المستخدم، لا سيما إذا كانت هذه البيانات تتضمن معلومات حساسة للمستخدم، يجب تعديلها أو محوها بعد استعادة الصفحة من ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات".

على سبيل المثال، إذا سجّل المستخدم الخروج من موقع إلكتروني على جهاز كمبيوتر عام ثم نقر المستخدم التالي على زر الرجوع، قد تتضمّن البيانات القديمة من "التخزين المؤقت للصفحات" بيانات خاصة كان المستخدم الأول من المتوقع محوها عند تسجيل الخروج.

لتجنُّب مثل هذه الحالات، عدِّل الصفحة دائمًا بعد حدث pageshow إذا كانت قيمة event.persisted هي true:

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Do any checks and updates to the page
  }
});

بالنسبة إلى بعض التغييرات، قد تحتاج إلى فرض إعادة تحميل كاملة بدلاً من ذلك، مع الحفاظ على سجلّ التنقّل لعمليات الانتقال للأمام. يتحقّق الرمز التالي من توفُّر ملف تعريف ارتباط خاص بالموقع الإلكتروني في حدث pageshow، ويُعيد التحميل في حال عدم العثور على ملف تعريف الارتباط:

window.addEventListener('pageshow', (event) => {
  if (event.persisted && !document.cookie.match(/my-cookie)) {
    // Force a reload if the user has logged out.
    location.reload();
  }
});

استعادة الإعلانات والتخزين المؤقت للصفحات

قد يكون من المغري تجنُّب استخدام ميزة "التخزين المؤقت للصفحات" حتى تتمكّن صفحتك من عرض مجموعة جديدة من الإعلانات عند كل عملية انتقال للخلف أو للأمام. إلا أنّ ذلك يؤثر سلبًا في أداء الموقع الإلكتروني ولا يؤدي إلى زيادة معدّل التفاعل مع الإعلان بشكل مستمر. على سبيل المثال، قد يريد المستخدم العودة إلى إحدى الصفحات للنقر على إعلان، ولكن إذا تمت إعادة تحميل الصفحة بدلاً من استعادتها من ميزة "التخزين المؤقت للصفحات"، قد يتم عرض إعلان مختلف. ننصح باستخدام اختبار A/B لتحديد أفضل استراتيجية لصفحتك.

بالنسبة إلى المواقع الإلكترونية التي تريد إعادة تحميل الإعلانات فيها عند استعادة ميزة "التخزين المؤقت للصفحات"، يمكنك إعادة تحميل الإعلانات فقط في حدث pageshow عندما تكون قيمة event.persisted هي true بدون التأثير في أداء الصفحة، كما هو موضّح في مثال علامة Google Publishing. للاطّلاع على مزيد من المعلومات حول أفضل الممارسات لموقعك الإلكتروني، يمكنك مراجعة ذلك مع مزوّد الإعلانات.

تجنُّب مراجع window.opener

في المتصفّحات القديمة، إذا تم فتح الصفحة باستخدام window.open() من رابط مع target=_blank، بدون تحديد rel="noopener"، ستحتوي الصفحة الافتتاحية على مرجع إلى عنصر النافذة في الصفحة المفتوحة.

بالإضافة إلى تشكّل الصفحة خطرًا أمنيًا، لا يمكن وضع صفحة ذات مرجع window.opener غير خالٍ بأمان في ميزة "التخزين المؤقت للصفحات" لأنّها قد تتسبّب في تعطّل أي صفحات تحاول الوصول إليها.

لتجنّب هذه المخاطر، استخدِم السمة rel="noopener" لمنع إنشاء مراجع window.opener. وهذا هو السلوك التلقائي في جميع المتصفحات الحديثة. إذا كان موقعك الإلكتروني بحاجة إلى فتح نافذة والتحكّم فيها باستخدام window.postMessage() أو من خلال الإشارة مباشرةً إلى عنصر النافذة، لن تكون النافذة المفتوحة أو أداة الفتح مؤهَّلتَين لاستخدام ميزة "التخزين المؤقت للصفحات".

إغلاق الاتصالات المفتوحة قبل انتقال المستخدم بعيدًا

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

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

ومع ذلك، إذا كانت هذه المهام مرتبطة بواجهات برمجة تطبيقات يمكن الوصول إليها أيضًا من صفحات أخرى في المصدر نفسه (على سبيل المثال: IndexedDB وWeb Locks وWebSockets)، قد يؤدي إيقافها مؤقتًا إلى إيقاف تلك الصفحات عن طريق منع تشغيل الرموز على تلك الصفحات.

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

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

يوضّح المثال التالي كيفية التأكّد من أنّ الصفحات التي تستخدم IndexedDB مؤهَّلة لاستخدام ميزة "التخزين المؤقت للصفحات" من خلال إغلاق اتصال مفتوح في مستمع حدث "pagehide":

let dbPromise;
function openDB() {
  if (!dbPromise) {
    dbPromise = new Promise((resolve, reject) => {
      const req = indexedDB.open('my-db', 1);
      req.onupgradeneeded = () => req.result.createObjectStore('keyval');
      req.onerror = () => reject(req.error);
      req.onsuccess = () => resolve(req.result);
    });
  }
  return dbPromise;
}

// Close the connection to the database when the user leaves.
window.addEventListener('pagehide', () => {
  if (dbPromise) {
    dbPromise.then(db => db.close());
    dbPromise = null;
  }
});

// Open the connection when the page is loaded or restored from bfcache.
window.addEventListener('pageshow', () => openDB());

الاختبار للتأكّد من أنّ صفحاتك قابلة للتخزين المؤقت

يمكن أن تساعدك "أدوات مطوري البرامج في Chrome" في اختبار صفحاتك لضمان تحسينها من أجل استخدام ميزة "التخزين المؤقت للصفحات" وتحديد أي مشاكل قد تمنعها من التأهُّل.

لاختبار صفحة:

  1. انتقِل إلى الصفحة في Chrome.
  2. في "أدوات مطوري البرامج"، انتقِل إلى التطبيق > التخزين المؤقت للصفحات.
  3. انقر على الزر إجراء اختبار. بعد ذلك، تحاول أدوات مطوّري البرامج الابتعاد عن الموقع الإلكتروني والرجوع إليه لتحديد ما إذا كان من الممكن استعادة الصفحة من خلال ميزة "التخزين المؤقت للصفحات".
لوحة "التخزين المؤقت للصفحات" في "أدوات مطوّري البرامج"
لوحة التخزين المؤقت للصفحات في "أدوات مطوري البرامج".

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

إذا كان السبب شيئًا يمكنك معالجته كمطوّر، تضع اللوحة علامة قابل للتنفيذ على السبب.

تعذُّر إعداد تقارير "أدوات مطوري البرامج" في استعادة صفحة من ذاكرة التخزين المؤقت للصفحات
تعذُّر اختبار ميزة "التخزين المؤقت للصفحات" والحصول على نتيجة قابلة للتنفيذ

في هذه الصورة، يؤدي استخدام أداة معالجة حدث unload إلى جعل الصفحة غير مؤهَّلة لاستخدام ميزة "التخزين المؤقت للصفحات". يمكن حلّ هذه المشكلة من خلال الانتقال من استخدام unload إلى pagehide:

الإجراءات التي يُنصح بها
window.addEventListener('pagehide', ...);
الإجراءات غير المُوصى بها
window.addEventListener('unload', ...);

وأضاف Lighthouse 10.0 عملية تدقيق إلى ذاكرة التخزين المؤقت التي تُجري اختبارًا مشابهًا. للحصول على مزيد من المعلومات، يمكنك الاطّلاع على مستندات تدقيق Bfcache.

كيفية تأثير ميزة "التخزين المؤقت للصفحات" في الإحصاءات وقياس الأداء

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

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

لتضمين عمليات استعادة ميزة "التخزين المؤقت للصفحات" في عدد مشاهدات الصفحة على الويب، اضبط أدوات معالجة الحدث pageshow وتحقَّق من السمة persisted.

يوضّح المثال التالي كيفية إجراء ذلك باستخدام "إحصاءات Google". من المحتمل أن تستخدم أدوات الإحصاءات الأخرى منطقًا مشابهًا:

// Send a pageview when the page is first loaded.
gtag('event', 'page_view');

window.addEventListener('pageshow', (event) => {
  // Send another pageview if the page is restored from bfcache.
  if (event.persisted) {
    gtag('event', 'page_view');
  }
});

قياس نسبة نتائج ميزة "التخزين المؤقت للصفحات"

لتحديد الصفحات التي لا تستخدم ميزة "التخزين المؤقت للصفحات" بعد، يمكنك قياس نوع التنقّل لعمليات تحميل الصفحات على النحو التالي:

// Send a navigation_type when the page is first loaded.
gtag('event', 'page_view', {
   'navigation_type': performance.getEntriesByType('navigation')[0].type;
});

window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Send another pageview if the page is restored from bfcache.
    gtag('event', 'page_view', {
      'navigation_type': 'back_forward_cache';
    });
  }
});

احسب نسبة نتائج ميزة "التخزين المؤقت للصفحات" باستخدام عدد عمليات الانتقال back_forward وback_forward_cache التي تم الانتقال إليها.

تشمل الأسباب التي قد تؤدي إلى عدم استخدام ميزة "التخزين المؤقت للصفحات" في التنقّل للخلف أو للأمام سلوك المستخدم التالي:

  • إنهاء المتصفح وإعادة تشغيله.
  • جارٍ تكرار علامة تبويب.
  • إغلاق علامة تبويب واستعادتها

في بعض هذه الحالات، قد يحتفظ المتصفّح بنوع التنقّل الأصلي ويعرض النوع back_forward على الرغم من عدم استخدام عمليات التنقّل للخلف أو للأمام. حتى إذا تم الإبلاغ عن أنواع التنقّل بشكل صحيح، يتم تجاهل ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات" بشكل دوري لتوفير الذاكرة.

لهذا السبب، لا يتوقّع مالكو المواقع الإلكترونية توقّع نسبة نتائج ميزة "التخزين المؤقت للصفحات" بنسبة 100% لجميع عمليات الانتقال في back_forward. ومع ذلك، يمكن أن يساعد قياس نِسبتها في تحديد الصفحات التي تمنع استخدام ميزة "التخزين المؤقت للصفحات".

يعمل فريق Chrome على تطوير واجهة برمجة تطبيقات NotRestoredReasons للمساعدة في توضيح أسباب عدم استخدام الصفحات لميزة "التخزين المؤقت للصفحات" حتى يتمكّن المطوّرون من تحسين معدلات نتائج التخزين المؤقت للصفحات.

قياس الأداء

باستخدام ميزة "التخزين المؤقت للصفحات" أيضًا في مقاييس الأداء التي يتم جمعها في الحقل، لا سيّما المقاييس التي تقيس أوقات تحميل الصفحة.

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

هناك عدة طرق للتعامل مع هذه المشكلة. الأولى هي إضافة تعليق توضيحي إلى جميع مقاييس تحميل الصفحات باستخدام نوع التنقل الخاص بها: navigate أو reload أو back_forward أو prerender. يتيح لك ذلك الاستمرار في مراقبة الأداء ضمن أنواع التنقل هذه، حتى إذا كان التوزيع العام ينحرف بشكل سلبي. ننصحك باستخدام هذا النهج مع مقاييس تحميل الصفحات التي لا تركّز على المستخدم، مثل الوقت المستغرق حتى أول بايت (TTFB).

بالنسبة إلى المقاييس التي تركّز على المستخدم مثل مؤشرات أداء الويب الأساسية، من الأفضل الإبلاغ عن قيمة تمثّل ما يختبره المستخدم بدقة أكبر.

التأثير في "مؤشرات أداء الويب الأساسية"

تقيس مؤشرات أداء الويب الأساسية تجربة المستخدم على صفحة ويب من خلال مجموعة متنوعة من السمات (سرعة التحميل والتفاعل والثبات البصري). من المهم أن تعكس مقاييس "مؤشرات أداء الويب الأساسية" إمكانية استعادة المستخدمين لميزة "التخزين المؤقت للصفحات" كعمليات تنقل أسرع مقارنةً بتحميل الصفحات التلقائية.

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

  • بالنسبة إلى سرعة عرض أكبر محتوى مرئي (LCP)، استخدِم علامة دلتا بين الطابع الزمني للحدث pageshow والطابع الزمني للإطار الملوّن التالي، لأنه سيتم عرض جميع العناصر في الإطار في الوقت نفسه. وفي حال استعادة ميزة "التخزين المؤقت للصفحات"، يكون مقياس LCP وFCP متماثلاً.
  • في حقل مدى استجابة الصفحة لتفاعلات المستخدم (INP)، يمكنك مواصلة استخدام "أداة مراقبة الأداء" الحالية، ولكن أعِد ضبط قيمة متغيّرات التصميم التراكمية (CLS) الحالية إلى 0.
  • بالنسبة إلى متغيّرات التصميم التراكمية (CLS)، يمكنك مواصلة استخدام "أداة مراقبة الأداء" الحالية، ولكن عليك إعادة ضبط قيمة متغيّرات التصميم التراكمية الحالية إلى 0.

للحصول على مزيد من التفاصيل حول كيفية تأثير ميزة "التخزين المؤقت للصفحات" في كل مقياس، يمكنك الاطّلاع على صفحات أدلّة المقاييس الفردية ضمن "مؤشرات أداء الويب الأساسية". للاطّلاع على مثال محدّد لكيفية تنفيذ إصدارات Bfcache لهذه المقاييس، يمكنك الرجوع إلى مقالة PR التي تتم إضافتها إلى مكتبة JavaScript لأحرف الويب الحيوية.

مراجع إضافية