Working with BFCache

Q: 什么是BFCache?

A: BFCache的意思是“后退前进缓存“(back-forward cache).查看如何使用Firefox的缓存了解更多详情.

Q: 当用户点击一个链接,当前标签中的页面跳转到一个新的页面之后,再点击浏览器的”后退“按钮,这时发生了什么?

A: The outer nsIDOMWindow (the |window| object in content JS, aka the <browser>'s contentWindow object in the parent document) stays right where it is.  It just has its inner window and document replaced.

The inner nsIDOMWindow (the global scope object in content JS) is either thrown away when GC happens, or frozen and placed in the bfcache.  When the user hits the 'back' button, either the window in bfcache is thawed or a new inner window is created, depending on whether there's a window in the bfcache.

Q: Is the page reloaded? loaded from cache? or is the DOM saved in some way as if the window was there but invisible? Are scripts recompiled? Where do they live while the page was invisible?

A: In the non-bfcache case, the page is reloaded in the sense of reparsing from the original HTML source.  That might come from the HTTP cache or not, depending on whether it's been evicted; typically it does come from the HTTP cache.  The DOM is recreated during the parsing process, scripts are recompiled (and also reloaded, probably from the HTTP cache).

In the bfcache case, freezing the window just marks it as frozen; the DOM is preserved, as are compiled script objects.  Thawing marks it as thawed.  Freezing suspends timeouts and interval timers on the frozen window, so they won't execute.  The script that's running when the window is frozen runs to completion, as it would if it were being closed, for example.  After that, only scripts running on other windows can touch this window; if they modify the DOM, the cached DOM and window is thrown away.

Q: 我们可以使用pagehide/pageshow事件来检测BFCache的使用情况,对吗?

A: 对.pagehide事件可以告诉你这个页面什么时候进入了bfcache,pageshow事件可以告诉你这个页面什么时候从bfcache中读取了出来.和其他缓存一下,这个页面存在有bfcache并不意味着这个bfcache一定会被用到.

Q: Hmm, so what event tells me “you'll never get a pageshow so you can drop the megabytes of info you've saved in Firebug side table for that page?”

A: An observer notification with the topic "inner-window-destroyed" whose subject is an nsISupportsPRUint64 containing the window id of the inner window being destroyed.