هنگام استفاده از دکمه های برگشت و جلو مرورگر، صفحات خود را برای بارگذاری فوری بهینه کنید.
کش عقب/ جلو (یا bfcache) یک بهینه سازی مرورگر است که پیمایش فوری به عقب و جلو را امکان پذیر می کند. این به طور قابل توجهی تجربه مرور را برای کاربران بهبود می بخشد - به خصوص کسانی که شبکه ها یا دستگاه های کندتر دارند.
به عنوان توسعه دهندگان وب، بسیار مهم است که بدانید چگونه صفحات خود را برای bfcache در همه مرورگرها بهینه کنید ، تا کاربران شما بتوانند از مزایای آن بهره ببرند.
سازگاری مرورگر
bfcache سالهاست که در فایرفاکس و سافاری ، در دسکتاپ و موبایل پشتیبانی میشود.
از نسخه 86، Chrome bfcache را برای پیمایش بین سایتی در اندروید برای درصد کمی از کاربران فعال کرد. در نسخه های بعدی، پشتیبانی اضافی به آرامی منتشر شد. از نسخه 96، bfcache برای همه کاربران Chrome در دسکتاپ و موبایل فعال است.
مبانی bfcache
bfcache یک کش در حافظه است که یک عکس فوری کامل از یک صفحه (شامل پشته جاوا اسکریپت) را در حین حرکت کاربر ذخیره می کند. با داشتن کل صفحه در حافظه، مرورگر می تواند به سرعت و به راحتی آن را بازیابی کند اگر کاربر تصمیم به بازگشت داشته باشد.
چند بار تا به حال از یک وب سایت بازدید کرده اید و روی پیوندی کلیک کرده اید تا به صفحه دیگری بروید، اما متوجه شده اید که آن چیزی نیست که می خواهید و روی دکمه بازگشت کلیک کنید؟ در آن لحظه، bfcache می تواند تفاوت زیادی در سرعت بارگیری صفحه قبلی ایجاد کند:
بدون فعال بودن bfcache | یک درخواست جدید برای بارگیری صفحه قبلی آغاز می شود، و بسته به اینکه چقدر آن صفحه برای بازدیدهای مکرر بهینه شده است، ممکن است مرورگر مجبور باشد برخی (یا همه) منابع را دوباره دانلود، تجزیه و تحلیل کند و دوباره اجرا کند. همین الان دانلود شد |
با فعال کردن bfcache | بارگیری صفحه قبلی اساساً فوری است، زیرا کل صفحه را می توان از حافظه بازیابی کرد، بدون اینکه اصلاً نیازی به رفتن به شبکه باشد. |
این ویدیوی عملی bfcache را تماشا کنید تا متوجه شوید که سرعتی که میتواند به پیمایشها بیاورد:
در ویدیوی بالا، مثال با bfcache کمی سریعتر از مثال بدون آن است.
bfcache نه تنها ناوبری را سرعت می بخشد، بلکه مصرف داده را نیز کاهش می دهد، زیرا منابع لازم نیست دوباره دانلود شوند.
دادههای استفاده از Chrome نشان میدهد که از هر 10 پیمایش در دسکتاپ، 1 و در تلفن همراه 1 مورد به عقب یا جلو هستند. با فعال کردن bfcache، مرورگرها می توانند انتقال داده و زمان صرف شده برای بارگذاری میلیاردها صفحه وب را در هر روز حذف کنند!
"کش" چگونه کار می کند
"کش" استفاده شده توسط bfcache با کش HTTP متفاوت است (که در سرعت بخشیدن به پیمایش های تکراری نیز مفید است). bfcache یک عکس فوری از کل صفحه در حافظه (شامل پشته جاوا اسکریپت) است، در حالی که کش HTTP فقط شامل پاسخ های درخواست های قبلی است. از آنجایی که بسیار نادر است که تمام درخواستهای مورد نیاز برای بارگیری یک صفحه از حافظه پنهان HTTP انجام شود، بازدیدهای مکرر با استفاده از بازیابیهای bfcache همیشه سریعتر از بهینهسازیشدهترین پیمایشهای غیرbfcache هستند.
با این حال، ایجاد یک عکس فوری از یک صفحه در حافظه، شامل پیچیدگی هایی از نظر بهترین روش حفظ کد در حال پیشرفت است. به عنوان مثال، چگونه میتوانید تماسهای setTimeout()
را در جایی که زمانی که صفحه در bfcache است، به زمان پایان رسیده است، مدیریت کنید؟
پاسخ این است که مرورگرها اجرای تایمرهای معلق یا وعدههای حلنشده را متوقف میکنند - اساساً تمام وظایف معلق در صفهای کار جاوا اسکریپت - و زمانی که (یا اگر) صفحه از bfcache بازیابی شد، وظایف پردازش را از سر میگیرند.
در برخی موارد این نسبتاً کم خطر است (به عنوان مثال، مهلت زمانی یا قول دادن)، اما در موارد دیگر ممکن است منجر به رفتار بسیار گیج کننده یا غیرمنتظره شود. به عنوان مثال، اگر مرورگر کاری را که به عنوان بخشی از تراکنش IndexedDB مورد نیاز است متوقف کند، میتواند سایر برگههای باز در همان مبدا را تحت تأثیر قرار دهد (زیرا همان پایگاههای داده IndexedDB میتواند توسط چندین تب به طور همزمان قابل دسترسی باشد). در نتیجه، مرورگرها معمولاً سعی نمیکنند صفحات را در وسط یک تراکنش IndexedDB یا با استفاده از APIهایی که ممکن است بر صفحات دیگر تأثیر بگذارد، کش کنند.
برای جزئیات بیشتر در مورد اینکه چگونه استفاده از API های مختلف بر واجد شرایط بودن bfcache صفحه تأثیر می گذارد، به بهینه سازی صفحات خود برای bfcache در زیر مراجعه کنید.
bfcache و برنامه های تک صفحه ای (SPA)
bfcache با ناوبری های مدیریت شده توسط مرورگر کار می کند. بنابراین، با به اصطلاح "ناوبری نرم" در یک SPA کار نمی کند، اما یکی از نقاط مهم فروش SPA این است که آن نوع از ناوبری ها باید به هر حال سریع باشند. با این حال، bfcache قطعاً میتواند در بازگشت به SPA به جای شروع مجدد کامل آن برنامه از ابتدا کمک کند.
API برای مشاهده bfcache
در حالی که bfcache یک بهینهسازی است که مرورگرها بهطور خودکار انجام میدهند، هنوز هم برای توسعهدهندگان مهم است که بدانند چه زمانی اتفاق میافتد تا بتوانند صفحات خود را برای آن بهینهسازی کنند و هر معیار یا اندازهگیری عملکرد را بر اساس آن تنظیم کنند .
رویدادهای اولیه مورد استفاده برای مشاهده bfcache رویدادهای انتقال صفحه هستند - pageshow
و pagehide
- که تا زمانی که bfcache وجود داشته است و تقریباً در همه مرورگرهای مورد استفاده امروز پشتیبانی میشود.
رویدادهای جدیدتر چرخه عمر صفحه - 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 پشتیبانی میکنند، هنگام بازیابی صفحات از bfcache (بلافاصله قبل از رویداد pageshow
) رویداد resume
نیز فعال میشود، هرچند زمانی که کاربر از یک برگه پسزمینه ثابت بازدید میکند نیز فعال میشود. اگر میخواهید وضعیت صفحه را پس از ثابت شدن (که شامل صفحاتی در bfcache میشود) بهروزرسانی کنید، میتوانید از رویداد resume
استفاده کنید، اما اگر میخواهید میزان بازدید bfcache سایت خود را اندازهگیری کنید، باید از رویداد pageshow
استفاده کنید. در برخی موارد، ممکن است لازم باشد از هر دو استفاده کنید.
مشاهده کنید که یک صفحه وارد bfcache می شود
رویداد pagehide
همتای رویداد pageshow
است. رویداد pageshow
زمانی فعال می شود که یک صفحه به طور معمول بارگیری شود یا از 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
استفاده نمیکنند، میتوانند با استفاده از خطمشی مجوزهای Chrome 115، اطمینان حاصل کنند که این موارد اضافه نشدهاند.
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 ذخیره نکنند. کار در حال انجام است تا این رفتار Chrome را به شیوه ای حفظ حریم خصوصی تغییر دهد ، اما در حال حاضر هیچ صفحه ای که Cache-Control: no-store
استفاده می کند برای bfcache واجد شرایط نخواهد بود.
از آنجایی که 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 بازیابی شد، میتوانید آن APIها را دوباره باز کنید یا دوباره به آن متصل شوید (در رویداد pageshow
یا resume
).
مثال زیر نشان میدهد که چگونه با بستن یک اتصال باز در شنونده رویداد 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 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 DevTools میتواند به شما کمک کند صفحات خود را آزمایش کنید تا مطمئن شوید برای bfcache بهینه شدهاند و هر مشکلی را که ممکن است مانع از واجد شرایط بودن آنها شود را شناسایی کنید.
برای آزمایش یک صفحه خاص، در Chrome به آن بروید و سپس در DevTools به Application > Back-Forward Cache بروید. سپس روی دکمه Run Test کلیک کنید و DevTools سعی میکند به دور و برگردید تا تعیین کند آیا صفحه را میتوان از bfcache بازیابی کرد یا خیر.
در صورت موفقیت آمیز بودن، پانل "بازیابی شده از حافظه پنهان عقب" را گزارش می دهد:
در صورت عدم موفقیت، پانل نشان می دهد که صفحه بازیابی نشده است و دلیل آن را ذکر می کند.
اگر دلیل چیزی است که شما بهعنوان یک توسعهدهنده میتوانید به آن بپردازید، آن نیز نشان داده میشود:
در تصویر بالا، استفاده از یک شنونده رویداد unload
، از واجد شرایط بودن صفحه برای bfcache جلوگیری می کند . میتوانید این مشکل را با تغییر از unload
به استفاده pagehide
برطرف کنید:
window.addEventListener('unload', ...);
window.addEventListener('pagehide', ...);
Lighthouse 10.0 همچنین یک ممیزی bfcache اضافه کرده است که آزمایش مشابهی را با آنچه DevTools انجام می دهد انجام می دهد و همچنین دلایلی را ارائه می دهد که چرا در صورت شکست ممیزی صفحه واجد شرایط نیست. برای اطلاعات بیشتر به اسناد حسابرسی bfcache نگاهی بیندازید.
چگونه bfcache بر تجزیه و تحلیل و اندازه گیری عملکرد تأثیر می گذارد
اگر بازدیدهای سایت خود را با یک ابزار تجزیه و تحلیل ردیابی کنید، احتمالاً متوجه کاهش تعداد کل بازدیدهای صفحه گزارش شده خواهید شد زیرا Chrome همچنان به فعال کردن bfcache برای کاربران بیشتر ادامه می دهد.
در واقع، احتمالاً در حال حاضر بازدیدهای صفحه از مرورگرهای دیگری که bfcache را پیادهسازی میکنند، کمتر گزارش میدهید، زیرا اکثر کتابخانههای تحلیلی محبوب، بازیابی bfcache را به عنوان بازدید از صفحه جدید ردیابی نمیکنند.
اگر نمیخواهید تعداد بازدید از صفحه شما به دلیل فعال کردن bfcache توسط Chrome کاهش یابد، میتوانید با گوش دادن به رویداد pageshow
و بررسی ویژگی persisted
، بازیابی bfcache را بهعنوان بازدید از صفحه (توصیهشده) گزارش کنید.
مثال زیر نحوه انجام این کار را با 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';
});
}
});
با نگاه کردن به نسبت ناوبری back_forward
به back_forward_cache
می توان نسبت bfcache را محاسبه کرد.
توجه به این نکته مهم است که تعدادی از سناریوها خارج از کنترل صاحبان سایت وجود دارد، زمانی که یک ناوبری Back/Forward از bfcache استفاده نمی کند، از جمله:
- زمانی که کاربر از مرورگر خارج می شود و دوباره آن را راه اندازی می کند
- وقتی کاربر یک برگه را کپی می کند
- زمانی که کاربر یک برگه را می بندد و آن را باز می کند
در برخی از این موارد، نوع ناوبری اصلی ممکن است توسط برخی از مرورگرها حفظ شود و بنابراین ممکن است یک نوع back_forward
را نشان دهد، علیرغم اینکه این ناوبری Back/Forward نیست.
حتی بدون آن استثناها، bfcache پس از مدتی برای حفظ حافظه حذف میشود.
بنابراین، صاحبان وبسایت نباید انتظار 100% نسبت ضربه bfcache را برای همه پیمایشهای back_forward
داشته باشند. با این حال، اندازهگیری نسبت آنها میتواند برای شناسایی صفحاتی مفید باشد که خود صفحه از استفاده از bfcache برای نسبت بالایی از پیمایشهای عقب و جلو جلوگیری میکند.
تیم Chrome در حال کار بر روی یک NotRestoredReasons
API است تا به افشای دلایل استفاده نشدن از 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 فعال باشد یا نه، فقط برای آنها اهمیت دارد که ناوبری سریع بوده است!
ابزارهایی مانند گزارش تجربه کاربر Chrome ، که معیارهای Core Web Vitals را جمعآوری و گزارش میکنند، بازیابیهای bfcache را بهعنوان بازدیدهای جداگانه از صفحه در مجموعه دادهشان تلقی میکنند.
و در حالی که (هنوز) APIهای عملکرد وب اختصاصی برای اندازهگیری این معیارها پس از بازیابی bfcache وجود ندارد، مقادیر آنها را میتوان با استفاده از APIهای وب موجود تقریبی کرد.
- برای بزرگترین رنگ محتوا (LCP) ، میتوانید از دلتای بین مهر زمانی رویداد
pageshow
و مهر زمانی فریم نقاشیشده بعدی استفاده کنید (زیرا همه عناصر قاب به طور همزمان نقاشی میشوند). توجه داشته باشید که در مورد بازیابی bfcache، LCP و FCP یکسان خواهند بود. - برای اولین تاخیر ورودی (FID) ، می توانید شنوندگان رویداد (همان مواردی که توسط FID polyfill استفاده می شود) را در رویداد
pageshow
دوباره اضافه کنید و FID را به عنوان تاخیر اولین ورودی پس از بازیابی bfcache گزارش کنید. - برای تغییر چیدمان تجمعی (CLS) ، میتوانید به استفاده از مشاهدهگر عملکرد موجود خود ادامه دهید. تنها کاری که باید انجام دهید این است که مقدار فعلی CLS را به 0 بازنشانی کنید.
برای جزئیات بیشتر در مورد اینکه bfcache چگونه بر هر معیار تأثیر می گذارد، به صفحات راهنمای متریک Core Web Vitals فردی مراجعه کنید. و برای مثالی خاص از نحوه پیادهسازی نسخههای bfcache این معیارها در کد، به PR مراجعه کنید و آنها را به کتابخانه web-vitals JS اضافه کنید .
منابع اضافی
- کش فایرفاکس (bfcache در فایرفاکس)
- کش صفحه (bfcache در سافاری)
- کش عقب/ جلو: رفتار در معرض وب (تفاوت bfcache در مرورگرها)
- آزمایشکننده bfcache (تست کنید که چگونه APIها و رویدادهای مختلف بر bfcache در مرورگرها تأثیر میگذارند)
- Performance Game Changer: Browser Back/Forward Cache (مطالعه موردی از مجله Smashing که بهبود چشمگیر Core Web Vitals را با فعال کردن bfcache نشان میدهد)