کش عقب/ جلو (یا bfcache) یک بهینه سازی مرورگر است که پیمایش فوری به عقب و جلو را امکان پذیر می کند. به طور قابل توجهی تجربه مرور را بهبود می بخشد، به خصوص برای کاربرانی که شبکه ها یا دستگاه های کندتر دارند.
به عنوان توسعه دهندگان وب، درک نحوه بهینه سازی صفحات خود برای bfcache بسیار مهم است تا کاربران شما بتوانند از مزایای آن بهره مند شوند.
سازگاری با مرورگر
همه مرورگرهای اصلی دارای bfcache هستند، از جمله کروم از نسخه 96، فایرفاکس و سافاری .
مبانی bfcache
با حافظه پنهان عقب/ جلو (bfcache)، به جای اینکه یک صفحه را زمانی که کاربر حرکت می کند، از بین ببریم، تخریب را به تعویق می اندازیم و اجرای JS را متوقف می کنیم. اگر کاربر به زودی به عقب بازگردد، صفحه را دوباره قابل مشاهده می کنیم و اجرای JS را لغو مکث می کنیم. این منجر به یک ناوبری صفحه تقریباً فوری برای کاربر می شود.
چند بار تا به حال از یک وب سایت بازدید کرده اید و روی پیوندی کلیک کرده اید تا به صفحه دیگری بروید، اما متوجه شده اید که آن چیزی نیست که می خواهید و روی دکمه بازگشت کلیک کنید؟ در آن لحظه، bfcache می تواند تفاوت زیادی در سرعت بارگیری صفحه قبلی ایجاد کند:
بدون فعال بودن bfcache | یک درخواست جدید برای بارگیری صفحه قبلی آغاز می شود، و بسته به اینکه چقدر آن صفحه برای بازدیدهای مکرر بهینه شده است، ممکن است مرورگر مجبور باشد برخی (یا همه) منابع را دوباره دانلود، تجزیه و تحلیل کند و دوباره اجرا کند. همین الان دانلود شد |
با فعال کردن bfcache | بارگیری صفحه قبلی اساساً فوری است، زیرا کل صفحه را می توان از حافظه بازیابی کرد، بدون اینکه اصلاً نیازی به رفتن به شبکه باشد. |
این ویدیوی عملی bfcache را تماشا کنید تا متوجه شوید که سرعتی که میتواند به پیمایشها بیاورد:
در ویدیو، مثال با bfcache کمی سریعتر از مثال بدون آن است.
bfcache نه تنها سرعت ناوبری را افزایش می دهد، بلکه مصرف داده را نیز کاهش می دهد، زیرا منابع لازم نیست دوباره دانلود شوند.
دادههای استفاده از Chrome نشان میدهد که از هر 10 پیمایش در دسکتاپ، 1 و در تلفن همراه 1 مورد به عقب یا جلو هستند. با فعال کردن bfcache، مرورگرها می توانند انتقال داده و زمان صرف شده برای بارگذاری میلیاردها صفحه وب را در هر روز حذف کنند!
"کش" چگونه کار می کند
"کش" استفاده شده توسط bfcache با حافظه پنهان HTTP متفاوت است، که نقش خود را در سرعت بخشیدن به پیمایش های تکراری ایفا می کند. bfcache یک عکس فوری از کل صفحه در حافظه، از جمله پشته جاوا اسکریپت است، در حالی که کش HTTP فقط شامل پاسخهای درخواستهای قبلی است. از آنجایی که بسیار نادر است که همه درخواستهای مورد نیاز برای بارگیری یک صفحه از حافظه پنهان HTTP انجام شود، بازدیدهای مکرر با استفاده از بازیابی bfcache همیشه سریعتر از بهینهسازیشدهترین پیمایشهای غیرbfcache هستند.
ثابت کردن یک صفحه برای فعال کردن مجدد آن بعداً شامل پیچیدگی هایی از نظر بهترین روش حفظ کد در حال پیشرفت است. به عنوان مثال، چگونه میتوانید تماسهای setTimeout()
را در جایی که زمانی که صفحه در bfcache است، به زمان پایان رسیده است، مدیریت کنید؟
پاسخ این است که مرورگرها تایمرهای معلق یا وعدههای حلنشده برای صفحات در bfcache، از جمله تقریباً تمام کارهای معلق در صفهای وظیفه جاوا اسکریپت را متوقف میکنند و در صورت بازیابی صفحه از bfcache، وظایف پردازش را از سر میگیرند.
در برخی موارد، مانند وقفه ها و وعده ها، این خطر نسبتا کم است، اما در موارد دیگر می تواند منجر به رفتار گیج کننده یا غیرمنتظره شود. به عنوان مثال، اگر مرورگر وظیفه ای را که به عنوان بخشی از تراکنش IndexedDB مورد نیاز است، متوقف کند، می تواند بر سایر برگه های باز در همان مبدا تأثیر بگذارد، زیرا همان پایگاه داده IndexedDB می تواند توسط چندین برگه به طور همزمان قابل دسترسی باشد. در نتیجه، مرورگرها معمولاً سعی نمیکنند صفحات را در وسط یک تراکنش IndexedDB یا در حین استفاده از APIهایی که ممکن است بر صفحات دیگر تأثیر بگذارند، کش کنند.
برای جزئیات بیشتر در مورد اینکه چگونه استفاده از API های مختلف بر واجد شرایط بودن bfcache صفحه تأثیر می گذارد، به بهینه سازی صفحات خود برای bfcache مراجعه کنید.
bfcache و iframes
اگر صفحه ای حاوی iframe های تعبیه شده باشد، خود iframe ها برای bfcache واجد شرایط نیستند. به عنوان مثال، اگر به صفحه دیگری در یک iframe بروید، اما سپس به عقب برگردید، مرورگر به جای اینکه در فریم اصلی باشد، به داخل iframe "بازگشت" میرود، اما پیمایش پشتی درون iframe از bfcache استفاده نمیکند.
اگر یک iframe تعبیهشده از APIهایی استفاده کند که این را مسدود میکنند، فریم اصلی نیز میتواند از استفاده از bfcache مسدود شود. برای جلوگیری از این امر می توان از خط مشی مجوزهای تنظیم شده بر روی قاب اصلی یا استفاده از ویژگی های sandbox
استفاده کرد.
bfcache و برنامه های تک صفحه ای (SPA)
از آنجا که bfcache با ناوبری های مدیریت شده توسط مرورگر کار می کند، برای "ناوبری نرم" در یک برنامه تک صفحه ای (SPA) کار نمی کند. با این حال، bfcache هنوز هم می تواند در بازگشت به SPA به جای شروع مجدد کامل آن برنامه از ابتدا کمک کند.
API برای مشاهده bfcache
اگرچه bfcache یک بهینهسازی است که مرورگرها بهطور خودکار انجام میدهند، اما همچنان برای توسعهدهندگان مهم است که بدانند چه زمانی اتفاق میافتد تا بتوانند صفحات خود را برای آن بهینهسازی کنند و هر معیار یا اندازهگیری عملکرد را بر اساس آن تنظیم کنند .
رویدادهای اصلی که برای مشاهده bfcache استفاده میشوند، رویدادهای انتقال صفحه pageshow
و pagehide
هستند که توسط اکثر مرورگرها پشتیبانی میشوند.
رویدادهای جدیدتر Page Lifecycle - freeze
و resume
- همچنین هنگام ورود یا خروج صفحات از bfcache و همچنین در برخی موقعیتهای دیگر ارسال میشوند، بهعنوان مثال، هنگامی که یک برگه پسزمینه ثابت میشود تا استفاده از CPU به حداقل برسد. این رویدادها فقط در مرورگرهای مبتنی بر Chromium پشتیبانی میشوند.
مشاهده کنید که یک صفحه از bfcache بازیابی می شود
رویداد pageshow
درست پس از رویداد load
زمانی که صفحه در ابتدا بارگذاری میشود و هر زمانی که صفحه از bfcache بازیابی میشود فعال میشود. رویداد pageshow
دارای یک ویژگی persisted
است که اگر صفحه از bfcache بازیابی شود true
است و در غیر این صورت false
. میتوانید از ویژگی persisted
برای تشخیص بارگذاریهای صفحه معمولی از بازیابیهای bfcache استفاده کنید. به عنوان مثال:
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('This page was restored from the bfcache.');
} else {
console.log('This page was loaded normally.');
}
});
در مرورگرهایی که از Page Lifecycle API پشتیبانی میکنند، رویداد resume
زمانی فعال میشود که صفحات از bfcache بازیابی میشوند (بلافاصله قبل از رویداد pageshow
) و زمانی که کاربر دوباره از یک برگه پسزمینه ثابت بازدید میکند. اگر میخواهید وضعیت صفحه را پس از ثابت شدن (که شامل صفحاتی در bfcache میشود) بهروزرسانی کنید، میتوانید از رویداد resume
استفاده کنید، اما اگر میخواهید میزان بازدید bfcache سایت خود را اندازهگیری کنید، باید از رویداد pageshow
استفاده کنید. در برخی موارد، ممکن است لازم باشد از هر دو استفاده کنید.
برای جزئیات بیشتر در مورد بهترین شیوه های اندازه گیری bfcache، ببینید چگونه bfcache بر تجزیه و تحلیل و اندازه گیری عملکرد تأثیر می گذارد .
مشاهده کنید که یک صفحه وارد bfcache می شود
رویداد pagehide
یا زمانی که صفحه ای بارگیری می شود یا زمانی که مرورگر سعی می کند آن را در bfcache قرار دهد فعال می شود.
رویداد pagehide
نیز دارای خاصیت persisted
است. اگر false
است، می توانید مطمئن باشید که آن صفحه قرار نیست وارد bfcache شود. با این حال، persisted
true
بودن، تضمینی برای ذخیره شدن یک صفحه در حافظه پنهان نیست. این بدان معناست که مرورگر قصد دارد صفحه را کش کند، اما ممکن است عوامل دیگری وجود داشته باشد که کش کردن آن را غیرممکن کند.
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
است، اما این فقط به این معنی است که مرورگر قصد دارد صفحه را کش کند. به دلایلی که بعدا توضیح داده شد، ممکن است همچنان مجبور باشد آن را کنار بگذارد.
صفحات خود را برای bfcache بهینه کنید
همه صفحات در bfcache ذخیره نمی شوند، و حتی زمانی که یک صفحه در آنجا ذخیره می شود، برای همیشه در آنجا باقی نمی ماند. بسیار مهم است که توسعه دهندگان بفهمند چه چیزی صفحات را واجد شرایط (و غیرقابل صلاحیت) برای bfcache می کند تا نرخ بازدید از حافظه پنهان خود را به حداکثر برسانند.
بخشهای زیر بهترین روشها را نشان میدهد تا به احتمال زیاد مرورگر بتواند صفحات شما را در حافظه پنهان کند.
هرگز از رویداد unload
استفاده نکنید
مهمترین راه برای بهینه سازی bfcache در همه مرورگرها این است که هرگز از رویداد unload
استفاده نکنید. همیشه!
رویداد unload
برای مرورگرها مشکل ساز است زیرا قبل از bfcache است و بسیاری از صفحات در اینترنت با این فرض (معقول) کار می کنند که یک صفحه پس از فعال شدن رویداد unload
به وجود خود ادامه نخواهد داد. این یک چالش است زیرا بسیاری از آن صفحات همچنین با این فرض ساخته شدهاند که هر زمانی که کاربر در حال حرکت است، رویداد unload
فعال میشود، که دیگر درست نیست (و برای مدت طولانی درست نبوده است ).
بنابراین مرورگرها با یک دوراهی روبرو هستند، آنها باید بین چیزی که می تواند تجربه کاربر را بهبود بخشد، یکی را انتخاب کنند - اما ممکن است خطر شکستن صفحه را نیز داشته باشد.
در دسکتاپ، کروم و فایرفاکس انتخاب کردهاند که اگر یک شنونده unload
اضافه کنند، صفحات را برای bfcache غیرقابل قبول کنند، که خطر کمتری دارد اما بسیاری از صفحات را نیز رد صلاحیت میکند. Safari سعی میکند برخی از صفحات را با یک شنونده رویداد حذف unload
، اما برای کاهش شکست احتمالی، رویداد unload
را زمانی که کاربر در حال حرکت است اجرا نمیکند، که این رویداد را بسیار غیرقابل اعتماد میکند.
در تلفن همراه، کروم و سافاری سعی میکنند صفحات را با یک شنونده رویداد unload
، زیرا خطر شکستگی کمتر است، زیرا رویداد unload
همیشه در تلفن همراه بسیار غیرقابل اعتماد بوده است. فایرفاکس صفحاتی را که از unload
استفاده می کنند برای bfcache واجد شرایط نیستند، به جز در iOS که همه مرورگرها را ملزم به استفاده از موتور رندر WebKit می کند، و بنابراین مانند سافاری رفتار می کند.
به جای استفاده از رویداد unload
، از رویداد pagehide
استفاده کنید. رویداد pagehide
در تمام مواردی که رویداد unload
فعال میشود فعال میشود و همچنین زمانی که صفحه در bfcache قرار میگیرد فعال میشود.
در واقع، Lighthouse دارای یک ممیزی no-unload-listeners
است، که اگر جاوا اسکریپتی در صفحات آنها (از جمله مواردی که از کتابخانه های شخص ثالث دریافت می شود) شنونده رویداد unload
اضافه کند، به توسعه دهندگان هشدار می دهد.
به دلیل غیرقابل اطمینان بودن و تأثیر عملکرد bfcache، Chrome به دنبال منسوخ کردن رویداد unload
است.
از خط مشی مجوز برای جلوگیری از استفاده از کنترل کننده های بارگیری در یک صفحه استفاده کنید
سایتهایی که از کنترلکنندههای رویداد unload
استفاده نمیکنند، میتوانند با استفاده از خطمشی مجوزها اطمینان حاصل کنند که اینها اضافه نشدهاند.
Permission-Policy: unload=()
این همچنین از کاهش سرعت سایت توسط اشخاص ثالث یا برنامههای افزودنی با اضافه کردن کنترلکنندههای بارگیری و عدم واجد شرایط ساختن سایت برای bfcache جلوگیری میکند.
فقط beforeunload
شنوندگان را به صورت مشروط اضافه کنید
رویداد beforeunload
باعث نمی شود صفحات شما برای bfcache در مرورگرهای مدرن bfcache واجد شرایط نباشند، اما قبلاً چنین بود و هنوز هم قابل اعتماد نیست، بنابراین از استفاده از آن اجتناب کنید مگر اینکه کاملاً ضروری باشد.
با این حال، برخلاف رویداد unload
، استفاده های قانونی برای beforeunload
وجود دارد. به عنوان مثال، هنگامی که می خواهید به کاربر هشدار دهید که تغییرات ذخیره نشده ای دارد، اگر صفحه را ترک کند، از دست خواهند داد. در این مورد، توصیه میشود که فقط زمانی که کاربر تغییرات ذخیرهنشدهای دارد، شنوندگان را beforeunload
اضافه کنید و بلافاصله پس از ذخیره تغییرات ذخیرهنشده، آنها را حذف کنید.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });
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
بر روی خود منبع صفحه تنظیم می شود (برخلاف هر منبع فرعی)، مرورگرها ترجیح می دهند صفحه را در bfcache ذخیره نکنند، بنابراین هر صفحه ای که از Cache-Control: no-store
استفاده می کند. Cache-Control: no-store
ممکن است واجد شرایط bfcache نباشد. کار در حال انجام است تا این رفتار Chrome را با حفظ حریم خصوصی تغییر دهد .
از آنجایی که Cache-Control: no-store
واجد شرایط بودن صفحه را برای bfcache محدود می کند، این صفحه فقط باید در صفحاتی تنظیم شود که حاوی اطلاعات حساسی هستند که در آن ذخیره سازی از هر نوعی هرگز مناسب نیست.
برای صفحاتی که نیاز دارند همیشه محتوای بهروز ارائه کنند - و این محتوا حاوی اطلاعات حساس نیست - از Cache-Control: no-cache
یا Cache-Control: max-age=0
استفاده کنید. این دستورالعملها به مرورگر دستور میدهند که محتوا را قبل از ارائه آن مجدداً تأیید کند، و بر واجد شرایط بودن bfcache صفحه تأثیری نمیگذارد.
توجه داشته باشید که وقتی صفحه ای از bfcache بازیابی می شود، از حافظه نه از کش HTTP بازیابی می شود. در نتیجه دستورالعملهایی مانند Cache-Control: no-cache
یا Cache-Control: max-age=0
در نظر گرفته نمیشوند و قبل از نمایش محتوا به کاربر، اعتبار مجددی رخ نمیدهد.
این احتمالاً تجربه کاربری بهتری است، با این حال، زیرا بازیابی های bfcache فوری هستند و - از آنجایی که صفحات برای مدت طولانی در bfcache باقی نمی مانند - بعید است که محتوا قدیمی باشد. با این حال، اگر محتوای شما دقیقه به دقیقه تغییر می کند، می توانید هر گونه به روز رسانی را با استفاده از رویداد pageshow
، همانطور که در بخش بعدی توضیح داده شده است، دریافت کنید.
پس از بازیابی bfcache، داده های قدیمی یا حساس را به روز کنید
اگر سایت شما وضعیت کاربر را حفظ می کند - به خصوص هر گونه اطلاعات حساس کاربر - این داده ها باید پس از بازیابی صفحه از bfcache به روز شوند یا پاک شوند.
به عنوان مثال، اگر کاربر به صفحه پرداخت پیمایش کند و سپس سبد خرید خود را به روز کند، اگر یک صفحه قدیمی از bfcache بازیابی شود، یک پیمایش به عقب به طور بالقوه می تواند اطلاعات قدیمی را نشان دهد.
مثال مهم دیگر این است که کاربر از یک سایت در یک رایانه عمومی خارج شود و کاربر بعدی دکمه بازگشت را کلیک کند. این به طور بالقوه میتواند دادههای خصوصی را که کاربر تصور میکرد هنگام خروج از سیستم پاک شده است، افشا کند.
برای جلوگیری از چنین موقعیتهایی، اگر event.persisted
true
است، همیشه صفحه را پس از یک رویداد pageshow
بهروزرسانی کنید:
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();
}
});
بارگذاری مجدد این مزیت را دارد که همچنان تاریخچه را حفظ می کند (برای پیمایش به جلو)، اما تغییر مسیر ممکن است در برخی موارد مناسب تر باشد.
بازیابی تبلیغات و bfcache
ممکن است وسوسه انگیز باشد که سعی کنید از استفاده از bfcache برای ارائه مجموعه ای جدید از تبلیغات در هر پیمایش عقب و جلو اجتناب کنید. با این حال، علاوه بر تاثیر بر عملکرد، این سوال وجود دارد که آیا چنین رفتاری منجر به تعامل بهتر با تبلیغات می شود یا خیر. کاربران ممکن است متوجه تبلیغاتی شده باشند که قصد داشتند دوباره کلیک کنند، اما با بارگذاری مجدد به جای بازیابی از bfcache قادر به انجام آن نیستند. آزمایش این سناریو – در حالت ایدهآل با آزمون A/B – قبل از انجام فرضیات مهم است.
برای سایتهایی که میخواهند تبلیغات را در بازیابی bfcache بهروزرسانی کنند، سپس تازه کردن تبلیغات در رویداد pageshow
زمانی که event.persisted
true
است، اجازه میدهد این کار بدون تأثیر بر عملکرد صفحه انجام شود. با ارائه دهنده تبلیغات خود تماس بگیرید، اما در اینجا یک مثال در مورد نحوه انجام این کار با برچسب انتشارات Google آورده شده است .
از مراجع window.opener
اجتناب کنید
در مرورگرهای قدیمیتر، اگر صفحهای با استفاده از window.open()
از پیوندی با target=_blank
، بدون تعیین rel="noopener"
باز میشود، صفحه باز شده به شی پنجره صفحه باز شده ارجاع میدهد.
علاوه بر این که یک خطر امنیتی است ، یک صفحه با مرجع window.opener
غیر تهی را نمی توان به طور ایمن در bfcache قرار داد، زیرا ممکن است هر صفحه ای را که سعی در دسترسی به آن داشته باشد، خراب کند.
در نتیجه، بهتر است از ایجاد مراجع window.opener
خودداری کنید. هر زمان که ممکن است می توانید این کار را با استفاده از rel="noopener"
انجام دهید (توجه داشته باشید، اکنون این پیش فرض در همه مرورگرهای مدرن است). اگر سایت شما نیاز به باز کردن یک پنجره و کنترل آن از طریق window.postMessage()
یا ارجاع مستقیم به شی پنجره داشته باشد، نه پنجره باز شده و نه بازکننده برای bfcache واجد شرایط نیستند.
قبل از اینکه کاربر حرکت کند، اتصالات باز را ببندید
همانطور که قبلا ذکر شد، زمانی که صفحه ای در bfcache نگه داشته می شود، تمام وظایف برنامه ریزی شده جاوا اسکریپت را متوقف می کند و زمانی که صفحه از کش خارج می شود، آنها را از سر می گیرد.
اگر این وظایف برنامهریزیشده جاوا اسکریپت فقط به APIهای DOM دسترسی دارند - یا سایر APIهای جدا شده از صفحه فعلی - در این صورت توقف موقت این وظایف در حالی که صفحه برای کاربر قابل مشاهده نیست، مشکلی ایجاد نمیکند.
با این حال، اگر این وظایف به APIهایی متصل شوند که از صفحات دیگر در همان مبدا نیز قابل دسترسی هستند (به عنوان مثال: IndexedDB، Web Locks، WebSockets) این می تواند مشکل ساز باشد زیرا توقف موقت این وظایف ممکن است از اجرای کد در برگه های دیگر جلوگیری کند.
در نتیجه، برخی از مرورگرها در سناریوهای زیر سعی نمیکنند صفحهای را در bfcache قرار دهند:
- صفحات با اتصال IndexedDB باز
- صفحات با fetch() در حال پیشرفت یا XMLHttpRequest
- صفحات با اتصال WebSocket یا WebRTC باز
اگر صفحه شما از هر یک از این APIها استفاده میکند، اکیداً توصیه میکنیم که اتصالات را ببندید و ناظران را در طول رویداد pagehide
یا freeze
حذف یا قطع کنید. این به مرورگر اجازه میدهد تا بهطور ایمن صفحه را بدون خطر تأثیرگذاری بر سایر برگههای باز ذخیره کند.
سپس، اگر صفحه از bfcache بازیابی شد، میتوانید در طول رویداد pageshow
یا resume
دوباره آن APIها را باز کنید یا دوباره به آن متصل شوید.
مثال زیر نشان می دهد که چگونه می توان با بستن یک اتصال باز در شنونده رویداد pagehide
، اطمینان حاصل کرد که صفحاتی که از IndexedDB برای bfcache استفاده می کنند، واجد شرایط هستند:
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 DevTools میتواند به شما کمک کند صفحات خود را آزمایش کنید تا مطمئن شوید برای bfcache بهینه هستند و هر مشکلی را که ممکن است مانع از واجد شرایط بودن آنها شود را شناسایی کنید.
برای تست یک صفحه:
- به صفحه کروم بروید.
- در DevTools، به Application -> Back-Forward Cache بروید.
- روی دکمه Run Test کلیک کنید. سپس DevTools سعی میکند به دور و برگردد تا تعیین کند آیا صفحه را میتوان از bfcache بازیابی کرد یا خیر.
اگر آزمایش موفقیت آمیز باشد، پانل "بازیابی از حافظه پنهان عقب به جلو" را گزارش می دهد.
اگر ناموفق باشد، پانل دلیل آن را نشان می دهد. اگر دلیل آن چیزی است که می توانید به عنوان یک توسعه دهنده به آن بپردازید، پانل آن را به عنوان Actionable علامت گذاری می کند.
در این مثال، استفاده از یک شنونده رویداد unload
باعث می شود صفحه برای bfcache واجد شرایط نباشد . میتوانید این مشکل را با تغییر از unload
به استفاده pagehide
برطرف کنید:
window.addEventListener('pagehide', ...);
window.addEventListener('unload', ...);
Lighthouse 10.0 همچنین یک حسابرسی bfcache اضافه کرد که آزمایش مشابهی را انجام می دهد. برای اطلاعات بیشتر، به اسناد حسابرسی bfcache مراجعه کنید.
چگونه bfcache بر تجزیه و تحلیل و اندازه گیری عملکرد تأثیر می گذارد
اگر از یک ابزار تجزیه و تحلیل برای اندازه گیری بازدید از سایت خود استفاده می کنید، ممکن است متوجه کاهش تعداد کل بازدیدهای صفحه گزارش شده شوید زیرا Chrome bfcache را برای کاربران بیشتری فعال می کند.
در واقع، احتمالاً در حال حاضر بازدیدهای صفحه از سایر مرورگرهایی که bfcache را پیادهسازی میکنند، کمتر گزارش میدهید، زیرا بسیاری از کتابخانههای تحلیلی محبوب، بازیابی bfcache را به عنوان بازدید از صفحه جدید اندازهگیری نمیکنند.
برای گنجاندن بازیابیهای bfcache در تعداد بازدید از صفحه خود، شنوندگان را برای رویداد pageshow
تنظیم کنید و ویژگی persisted
را بررسی کنید.
مثال زیر نحوه انجام این کار را با Google Analytics نشان می دهد. سایر ابزارهای تحلیلی احتمالاً از منطق مشابهی استفاده می کنند:
// 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 خود را اندازه گیری کنید
همچنین ممکن است بخواهید اندازه گیری کنید که آیا از bfcache استفاده شده است یا خیر تا به شناسایی صفحاتی که از 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';
});
}
});
نسبت ضربه های bfcache خود را با استفاده از تعداد پیمایش های back_forward
و back_forward_cache
محاسبه کنید.
توجه به این نکته مهم است که تعدادی از سناریوها خارج از کنترل صاحبان سایت وجود دارد، زمانی که یک ناوبری Back/Forward از bfcache استفاده نمی کند، از جمله:
- زمانی که کاربر از مرورگر خارج می شود و دوباره آن را راه اندازی می کند
- وقتی کاربر یک برگه را کپی می کند
- زمانی که کاربر یک برگه را می بندد و دوباره آن را باز می کند
در برخی از این موارد، نوع ناوبری اصلی ممکن است توسط برخی از مرورگرها حفظ شود و بنابراین ممکن است یک نوع back_forward
را نشان دهد، علیرغم اینکه این ناوبری Back/Forward نیست.
حتی بدون آن استثناها، bfcache پس از مدتی برای حفظ حافظه حذف میشود.
بنابراین، صاحبان وبسایت نباید انتظار 100% نسبت ضربه bfcache را برای همه پیمایشهای back_forward
داشته باشند. با این حال، اندازهگیری نسبت آنها میتواند برای شناسایی صفحاتی مفید باشد که خود صفحه از استفاده از bfcache برای نسبت بالایی از پیمایشهای عقب و جلو جلوگیری میکند.
تیم Chrome API NotRestoredReasons
را اضافه کرده است تا به افشای دلایل عدم استفاده صفحات از bfcache کمک کند تا توسعه دهندگان بتوانند نرخ بازدید bfcache خود را بهبود بخشند. تیم کروم همچنین انواع ناوبری را به CrUX اضافه کرده است که امکان مشاهده تعداد پیمایشهای bfcache را حتی بدون اندازهگیری خودتان ممکن میسازد.
اندازه گیری عملکرد
bfcache همچنین می تواند بر معیارهای عملکرد جمع آوری شده در این زمینه تأثیر منفی بگذارد، به ویژه معیارهایی که زمان بارگذاری صفحه را اندازه گیری می کنند.
از آنجایی که پیمایشهای bfcache به جای شروع بارگذاری صفحه جدید، یک صفحه موجود را بازیابی میکنند، وقتی bfcache فعال شود، تعداد کل بارگیریهای صفحه جمعآوریشده کاهش مییابد. با این حال، آنچه مهم است، این است که بارگذاری صفحه با بازیابیهای bfcache جایگزین میشود، احتمالاً برخی از سریعترین بارگذاریهای صفحه در مجموعه داده شما بوده است. این به این دلیل است که پیمایشهای عقب و جلو، طبق تعریف، بازدیدهای مکرر هستند و بارگیری مجدد صفحه عموماً سریعتر از بارگیری صفحه از بازدیدکنندگانی است که برای اولین بار انجام میشود (به دلیل ذخیره HTTP ، همانطور که قبلاً ذکر شد).
نتیجه، بارگذاری سریع صفحه کمتر در مجموعه داده شما است، که احتمالاً توزیع را کندتر می کند - علی رغم این واقعیت که عملکرد تجربه شده توسط کاربر احتمالاً بهبود یافته است!
چند راه برای مقابله با این موضوع وجود دارد. یکی این است که تمام معیارهای بارگذاری صفحه را با نوع پیمایش مربوطه آن ها حاشیه نویسی کنید: navigate
، reload
، back_forward
یا prerender
. این به شما امکان می دهد عملکرد خود را در این انواع پیمایش نظارت کنید، حتی اگر توزیع کلی منحرف شود. ما این رویکرد را برای معیارهای بارگذاری صفحه غیر کاربر محور مانند زمان تا اولین بایت (TTFB) توصیه می کنیم.
برای معیارهای کاربر محور مانند Core Web Vitals ، گزینه بهتر این است که مقداری را گزارش کنید که با دقت بیشتری آنچه را که کاربر تجربه می کند، نشان دهد.
تاثیر بر Core Web Vitals
Core Web Vitals تجربه کاربر از یک صفحه وب را در ابعاد مختلف (سرعت بارگذاری، تعامل، ثبات بصری) اندازهگیری میکند و از آنجایی که کاربران بازیابی bfcache را به عنوان ناوبری سریعتر از بارگذاری کامل صفحه تجربه میکنند، مهم است که معیارهای Core Web Vitals این را منعکس کند. . از این گذشته، یک کاربر برایش مهم نیست که bfcache فعال باشد یا نه، فقط به این اهمیت می دهد که ناوبری سریع بوده است!
ابزارهایی که معیارهای Core Web Vitals را جمعآوری و گزارش میکنند، مانند گزارش تجربه کاربر Chrome ، بازیابیهای bfcache را بهعنوان بازدیدهای جداگانه از صفحه در مجموعه داده خود در نظر میگیرند. و در حالی که APIهای عملکرد وب اختصاصی برای اندازهگیری این معیارها پس از بازیابی bfcache وجود ندارد، میتوانید مقادیر آنها را با استفاده از APIهای وب موجود تقریبی کنید:
- برای بزرگترین رنگ محتوایی (LCP) ، از دلتا بین مهر زمانی رویداد
pageshow
و مهر زمانی فریم نقاشی شده بعدی استفاده کنید، زیرا همه عناصر در قاب به طور همزمان نقاشی می شوند. در مورد بازیابی bfcache، LCP و FCP یکسان هستند. - برای Interaction to Next Paint (INP) ، به استفاده از مشاهده عملکرد موجود خود ادامه دهید، اما مقدار INP فعلی را به 0 بازنشانی کنید.
- برای تغییر چیدمان تجمعی (CLS) ، به استفاده از مشاهده عملکرد موجود خود ادامه دهید، اما مقدار CLS فعلی را به 0 بازنشانی کنید.
برای جزئیات بیشتر در مورد اینکه چگونه bfcache بر هر متریک تأثیر می گذارد، به صفحات راهنمای متریک Core Web Vitals فردی مراجعه کنید. برای مثالی خاص از نحوه پیادهسازی نسخههای bfcache این معیارها، به PR مراجعه کنید که آنها را به کتابخانه web-vitals JS اضافه میکند .
کتابخانه جاوا اسکریپت web-vitals از بازیابی های bfcache در معیارهایی که گزارش می کند پشتیبانی می کند .
منابع اضافی
- کش فایرفاکس (bfcache در فایرفاکس)
- کش صفحه (bfcache در سافاری)
- کش عقب/ جلو: رفتار در معرض وب (تفاوت bfcache در مرورگرها)
- آزمایشکننده bfcache (تست اینکه چگونه APIها و رویدادهای مختلف بر bfcache در مرورگرها تأثیر میگذارند)
- Performance Game Changer: Browser Back/Forward Cache (مطالعه موردی از مجله Smashing که بهبود چشمگیر Core Web Vitals را با فعال کردن bfcache نشان میدهد)