ある日仕事でWebサイトを作っていたのですが、iPhone実機のiOS Safariでハンバーガーメニューのリンクからページ遷移した後ブラウザバックをすると、メニューが開きっぱなしになっているなどの現象が起きてました。
PCでスマホ表示を確認しても同じ現象は起きていませんでしたが、実機で確認するとどうやらブラウザバックしてもリロードが入っていなかったりJS(jQuery)がページ遷移前のままの状態になっているようでした。
「何これ?」と思っていろいろ調べて最終的に解決できたのでそのお話をします。
原因はiOS Safariの「bfcache」という機能だった
「bfcache(Back/Forward cache)」とは、簡単に言うとページ遷移前の状態をキャッシュとしてメモリ上に保存し、ブラウザバックしてきたときにそのキャッシュを表示することで高速でページを表示できるという機能です。
戻る/進むボタンを押したときに発火するらしいですが、必ず発火するわけではない?らしいです(この辺はよくわからない)。あとFirefoxでも同じことが起こる?みたいです(スマホ実機でFirefoxは検証していないのでわかりませんが、もしかしたら起こるかも)。
また、bfcacheではJSのonloadイベントが起きないため、ページの再読み込みがされず、結果としてページ遷移の直前の状態がそのまま表示されてしまうというわけです。これがハンバーガーメニュが開きっぱなしになっているとかの原因ですね。
bfcache対策の仕方
bfcacheは以下のような処理で対処可能です。イベントの部分はjQueryではなくJavaScriptで書く必要があるみたいです(中の処理はjQueryでもok)。
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
// bfcache発動時の処理
window.location.reload();
}
});
window.addEventListener('pageshow')
の部分はwindow.onpageshow = function(event) {}
と書いてもokです。
'pageshow'
はページの表示が完了したときに呼ばれるイベントです。bfcacheのときは'load'
ではなく'pageshow'
を使うようにしてください。
event.persisted
でbfcacheが発動しているかどうかをチェックできます。発動している場合はtrueになります。このif文の中にbfcacheが発動している時の処理を書けばいいわけですね。
bfcacheの一番簡単な対策はリロードすることです。
もしリロードしたくないならbfcacheが原因で表示が崩れている部分を修正する処理を書けばokです(ハンバーガーメニューが開きっぱなしになっているならそれを閉じる処理を書けばok)。
参考リンク
bfcacheについて知りたい人はとりあえず以下の記事を読んでおくのがいいです。
まとめ
スマホ実機で確認してみないとわからないのがなかなか気づきにくいポイントですが、一応ちゃんと対策はあります。
bfcacheの対策自体は他にも方法があるみたいですが、iOS Safariだけはこの方法じゃないとダメみたいです。
なんかiOS Safariってこういう変な所あるよね…。嫌いです。