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

حسِّن صفحاتك لتتلاءم عمليات التحميل الفورية عند استخدام زرَّي الرجوع وإعادة التوجيه في المتصفِّح.

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

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

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

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

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

أساسيات Bfcache

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

كم مرة زرت أحد المواقع الإلكترونية ونقرت على رابط للانتقال إلى صفحة أخرى، لتدرك أنه ليس ما تريده، ثم نقرت على زر الرجوع؟ في تلك اللحظة، يمكن لميزة bfcache إحداث فرق كبير في مدى سرعة تحميل الصفحة السابقة:

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

شاهِد هذا الفيديو لاستخدام ميزة "التخزين المؤقت للصفحات" بشكل عملي لفهم سرعته في التنقّل:

في الفيديو أعلاه، فإن المثال الذي يتضمن bfcache أسرع قليلاً من المثال الذي لا يتضمنه.

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

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

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

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

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

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

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

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

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

تعمل ميزة "التخزين المؤقت للصفحات" مع عمليات التنقّل التي يديرها المتصفّح. لذلك، لا يتناسب هذا الخيار مع ما يُعرف باسم "عمليات التنقّل البسيطة" داخل SPA، ولكنّ إحدى أهم الميزات التنافسية في 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.');
  }
});

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

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

الحدث pagehide هو نظير حدث pageshow. يتم تنشيط حدث 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 فقط إلى تخزين الصفحة في ذاكرة التخزين المؤقت. قد لا يزال يتعين عليه تجاهلها لعدد من الأسباب الموضحة أدناه.

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

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

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

عدم استخدام حدث "unload" مطلقًا

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

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

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

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

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

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

في الواقع، تتضمن Lighthouse عملية تدقيق no-unload-listeners، ستحذّر المطوّرين في حال إضافة أي أداة JavaScript على صفحاتهم (بما في ذلك النص البرمجي من المكتبات التابعة لجهات خارجية) إلى أداة معالجة حدث unload.

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

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

يمكن للمواقع الإلكترونية التي لا تستخدم معالِجات أحداث unload ضمان عدم إضافتها باستخدام سياسة الأذونات من الإصدار 115 من Chrome.

Permission-Policy: unload()

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

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

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

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

الإجراءات غير المُوصى بها
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
يضيف الرمز أعلاه مستمع 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);
});
يضيف الرمز البرمجي أعلاه مستمِع beforeunload عند الحاجة فقط (ويزيله عند عدم الحاجة).

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

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

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

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

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

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

لا تزال هذه تجربة أفضل للمستخدم، مع ذلك، فعمليات استعادة ميزة "التخزين المؤقت للصفحات" تتم بشكل فوري، وبما أنّ الصفحات لا تظل في ذاكرة التخزين المؤقت لفترة طويلة جدًا، من غير المرجّح أن يكون المحتوى قديمًا. ومع ذلك، إذا كان المحتوى يتغيّر كل دقيقة، يمكنك استرجاع أي تعديلات باستخدام حدث 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 غير خالٍ بأمان في ذاكرة التخزين المؤقت لميزة "التخزين المؤقت للصفحات" لأنّ ذلك قد يؤدي إلى تعطّل أي صفحات تحاول الوصول إليها.

نتيجةً لذلك، من الأفضل تجنّب إنشاء مراجع window.opener. ويمكنك إجراء ذلك باستخدام rel="noopener" كلما أمكن ذلك (لاحظ أنّ هذا هو الإعداد التلقائي في جميع المتصفحات الحديثة). إذا كان موقعك الإلكتروني يتطلّب فتح نافذة والتحكّم فيها من خلال 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 is leaving.
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" في اختبار صفحاتك لضمان تحسينها من أجل استخدام ميزة "التخزين المؤقت للصفحات" وتحديد أي مشاكل قد تمنعها من التأهُّل.

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

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

في حال نجاح هذا الإجراء، ستعرض اللوحة رسالة "تمت الاستعادة من ميزة "التخزين المؤقت للصفحات":

الإبلاغ عن صفحة في "أدوات مطوري البرامج" تمت استعادتها بنجاح من ميزة "التخزين المؤقت للصفحات"

إذا لم تنجح هذه الخطوات، ستشير اللوحة إلى عدم استعادة الصفحة وتعرض السبب.

إذا كان السبب شيئًا يمكنك أنت المطور معالجته، سيشار إليه أيضًا:

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

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

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

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

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

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

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

إذا كنت لا تريد أن ينخفض عدد مشاهدات الصفحة على الويب بسبب تفعيل Chrome لميزة "التخزين المؤقت للصفحات"، يمكنك الإبلاغ عن عمليات استعادة ميزة "التخزين المؤقت للصفحات" كمشاهدات للصفحة (يُنصَح به) من خلال الاستماع إلى حدث 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');
  }
});

قياس نسبة نتائج Bfcache

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

// 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 تعمل على استعادة صفحة حالية بدلاً من بدء تحميل صفحة جديدة، سينخفض إجمالي عدد عمليات تحميل الصفحات التي تم جمعها عند تفعيل ميزة "التخزين المؤقت للصفحات". لكن المهم هو أن تحميل الصفحة التي يتم تحميلها باستعادة البيانات من خلال bfcache قد يكون من أسرع تحميل الصفحات في مجموعة البيانات لديك. ويرجع ذلك إلى أنّ عمليات الانتقال إلى الخلف وإلى الأمام، حسب تعريفها، هي زيارات متكرّرة، كما أنّ عمليات تحميل الصفحات المتكرّرة تكون بشكل عام أسرع من عمليات تحميل الصفحات التي يجريها الزائرون للمرة الأولى (بسبب التخزين المؤقت باستخدام بروتوكول HTTP، كما هو مذكور سابقًا).

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

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

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

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

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

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

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

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

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

مراجع إضافية