صارفین براؤزر میں تقریباً کسی بھی دوسرے کنٹرول کے مقابلے میں بیک (back) بٹن کا استعمال زیادہ کرتے ہیں۔ وہ توقع کرتے ہیں کہ پچھلی اسکرین فوری طور پر بالکل اسی جگہ ظاہر ہو جہاں انہوں نے اسے چھوڑا تھا۔ جدید براؤزرز back/forward cache، یا bfcache کے ذریعے اس توقع کو پورا کرتے ہیں۔ جب آپ کسی پیج سے دوسرے پیج پر جاتے ہیں، تو براؤزر اسے ختم کرنے کے بجائے میموری میں فریز (freeze) کر دیتا ہے۔ جب آپ واپس آتے ہیں، تو یہ اس کا ایک اسنیپ شاٹ (snapshot) بحال کر دیتا ہے۔ براؤزر HTML کی پارسنگ، JavaScript کو دوبارہ چلانے، اور layout کی دوبارہ کیلکولیشن کرنے کے عمل کو چھوڑ دیتا ہے۔ نتیجہ فوری محسوس ہوتا ہے کیونکہ پیج کبھی مکمل طور پر ختم ہی نہیں ہوا۔

bfcache اصل میں کیا کرتا ہے

ایک عام پیج لوڈ ہونا ایک مہنگا عمل ہے۔ براؤزر کو ریسورسز حاصل کرنے، HTML کو ٹوکنائز کرنے، DOM بنانے، اسکرپٹس چلانے، اسٹائلز کو حل کرنے، layout کرنے، پکسلز پینٹ کرنے اور لیئرز کو کمپوزٹ کرنے کی ضرورت ہوتی ہے۔ bfcache پیج کو RAM میں فریز حالت میں زندہ رکھ کر ان میں سے تقریباً تمام مراحل سے بچ جاتا ہے۔ یہ ڈسک کیش (disk cache) نہیں ہے۔ رینڈر شدہ پیج، بشمول JavaScript heap، scroll position، اور form state، میموری میں موجود رہتا ہے جب تک صارف اگلا پیج پڑھ رہا ہوتا ہے۔ جب صارف بیک پر کلک کرتا ہے، تو براؤزر اسنیپ شاٹ کو پگھلا دیتا ہے اور pageshow ایونٹ فائر کرتا ہے۔ پیج نیٹ ورک کو چھوئے بغیر یا شروع سے layout دوبارہ کیے بغیر وہیں سے شروع ہو جاتا ہے۔ سست ڈیوائسز یا کمزور کنکشن والے صارفین کے لیے، bfcache کی بحالی اور ایک نئے لوڈ کے درمیان فرق سینکڑوں ملی سیکنڈز یا اس سے بھی زیادہ ہو سکتا ہے۔

کیا چیز اسے روکتی ہے

ایک ڈویلپر نے حال ہی میں یہ جاننے کے لیے ایک تجربہ کیا کہ اصل میں کون سی چیز bfcache کو روکتی ہے۔ انہوں نے چھ سادہ پیجز بنائے، جن میں سے ہر ایک ایک مشکوک رکاوٹ کا تجربہ کر رہا تھا، پھر وہ پیج سے ہٹ گئے اور بیک دبایا۔ نتائج واضح تھے۔

ایک بیس لائن پیج جس میں کوئی غیر معمولی ہیڈرز یا اسکرپٹس نہیں تھے، کامیابی سے بحال ہو گیا۔ ایک پیج جس میں beforeunload listener تھا، وہ بھی بغیر کسی مسئلے کے بحال ہو گیا۔ حیرت انگیز طور پر، Cache-Control: no-store کے ساتھ سروس کیا جانے والا پیج بھی bfcache میں داخل ہو گیا، جو پرانی رہنمائی کے برعکس تھا۔ یہاں تک کہ ایک لائیو بلاگ آرٹیکل، جو فریز کرنے کے لیے بہت زیادہ ڈائنامک معلوم ہو سکتا ہے، کامیابی سے بحال ہو گیا۔

دو پیجز ناکام رہے۔ ایک پیج جس میں unload event listener تھا، اسے بحال نہیں کیا جا سکا۔ ایک پیج جس میں کھلا ہوا WebSocket کنکشن تھا، وہ بھی بلاک ہو گیا۔ یہ دو ناکامیاں ان جالوں کی طرف اشارہ کرتی ہیں جو روزانہ حقیقی پروڈکشن سائٹس کو پھنساتے ہیں۔

unload ایونٹ کا جال

unload ایونٹ طویل عرصے سے آخری لمحے کی صفائی (cleanup) کے لیے ایک سگنل کے طور پر استعمال ہوتا رہا ہے۔ ڈویلپرز اسے اینالیٹکس بیکنز (analytics beacons) کو فلش کرنے، ٹائمرز کو ختم کرنے، یا عارضی اسٹیٹ کو صاف کرنے کے لیے استعمال کرتے ہیں۔ مسئلہ یہ ہے کہ bfcache اس خیال پر مبنی ہے کہ پیج دوبارہ زندہ ہو سکتا ہے۔ اگر براؤزر کو unload listener نظر آتا ہے، تو وہ فرض کر لیتا ہے کہ پیج مکمل طور پر ختم ہونے کی توقع رکھتا ہے اور اسے فریز کرنے سے انکار کر دیتا ہے۔ اس سے کوئی فرق نہیں پڑتا کہ منسلک فنکشن خالی ہے۔ صرف اس listener کی موجودگی ہی ہر جدید براؤزر میں کیشنگ کو روکنے کے لیے کافی ہے۔

اس کا متبادل pagehide ہے۔ یہ ایونٹ اس وقت بھی فائر ہوتا ہے جب پیج کو bfcache کے لیے فریز کیا جا رہا ہو اور اس وقت بھی جب اسے واقعی ختم کیا جا رہا ہو۔ اگر آپ کو ان دونوں کے درمیان فرق کرنے کی ضرورت ہے، تو جب پیج bfcache کی طرف جا رہا ہو تو event.persisted پراپرٹی true ہوتی ہے۔ تاہم، زیادہ تر صفائی کے کاموں کے لیے، pagehide دونوں صورتوں کا احاطہ کرتا ہے۔ صفائی کے ہر منطقی حصے کو unload سے نکال کر pagehide میں منتقل کر دیں۔ پھر ہر unload listener کو مکمل طور پر ختم کر دیں، بشمول وہ جو تھرڈ پارٹی اینالیٹکس اسنیپٹس یا پرانے پلگ انز میں چھپے ہوئے ہیں۔

ایکٹو کنکشن کے جال

ایک کھلا ہوا نیٹ ورک یا اسٹوریج کنکشن اس بات کا اشارہ ہے کہ آپ کا پیج اب بھی حقیقی کام کر رہا ہے۔ براؤزر نیویگیشن کے وقت ایکٹو ریسورسز کا جائزہ لیتا ہے۔ اگر اسے کوئی کھلا ہوا WebSocket، ایک ایکٹو WebRTC peer connection، یا کوئی برقرار IndexedDB کنکشن ملتا ہے، تو وہ فریز کرنے کا عمل روک دیتا ہے اور پیج کو معمول کے مطابق ختم کر دیتا ہے۔ جب تک ڈیٹا (bytes) بہہ رہا ہو سکتا ہے، اسنیپ شاٹ پر بھروسہ نہیں کیا جا سکتا۔

آپ کو یہ ریسورسز pagehide listener کے اندر بند کرنے چاہئیں۔ اپنے WebSocket کا close میتھڈ کال کریں۔ WebRTC peer connections کو بند کریں۔ کسی بھی زیر التواء IndexedDB ٹرانزیکشنز کو منسوخ یا کمٹ کریں۔ اگر آپ کی ایپ کو صارف کے واپس آنے پر ان چینلز کی ضرورت ہے، تو انہیں pageshow کے اندر دوبارہ کھولیں۔ یہ close-on-pagehide, restore-on-pageshow پیٹرن پیج کو فنکشنلٹی کھوئے بغیر فوری بیک نیویگیشن کے لیے اہل رکھتا ہے۔

no-store کا حیرت انگیز پہلو

برسوں تک، روایتی عقیدہ یہ تھا کہ Cache-Control: no-store bfcache کو روکتا ہے۔ Chrome نے 2025 میں اس رویے کو بدل دیا۔ اب no-store کے ساتھ سروس کیا جانے والا پیج bfcache میں داخل ہو سکتا ہے۔ براؤزر فریز شدہ اسنیپ شاٹ کو صرف اس صورت میں بعد میں نکالتا ہے اگر آتھنٹیکیشن اسٹیٹس یا کوکیز اس طرح بدل جائیں کہ محفوظ شدہ اسٹیٹ کالعدم ہو جائے۔ اگر آپ no-store کو بطور