【ようこそSafariパークへ①】ブラウザバックするとJavaScriptが動かない不具合への対策

once upon a time……

スクールの最終課題の機能があらかた揃い、ひとまず手動で動作を確認していた私、とあることに気がつく。

Safariで見ると、想定していた挙動と違う……。』


不具合詳細

作成中の自作アプリには、様々な検索機能を実装しているのですが、

どの検索結果から遷移した先の詳細画面に、『前のページに戻る』というボタンを置き、元の検索結果に戻れるようにしていました。

= button_to '検索結果に戻る', artist_path, id: 'artist-name-search__back', class: 'btn btn-green400 float-right', onClick: 'history.go(-1); return false;', data: {"turbolinks" => false}

history.go(-1)が履歴を通してひとつ前のページに戻る処理。ブラウザバックですね。

しかし return false; を付けておかないとうまく動きません 。なぜかはあんまりわかっていない……。

clickにつけるとa要素の処理を中断してくれるものであると解釈している。

onclick="javascript:history.go(-1)" not working in Chrome - Stack Overflow

javascriptのreturn falseの意味や使い方 | よの冒険記

ちなみに、最初はbutton_toなら生成されるのaタグじゃないし……と思ってdata: {"turbolinks" => false}を入れていなかったのですが、

ブラウザのデベロッパツールで確認すると以下のような感じに展開されているんですよね。

<form class="button_to" method="post" action="/artists/1zdg5hNDqpWtsN35ME7JuZ">
  <input id="artist-name-search__back" class="btn btn-green400 float-right" onclick="history.go(-1); return false;" data-turbolinks="false" type="submit" value="検索結果に戻る">
  <input type="hidden" name="authenticity_token" value="F450xZvL6JF/FP5kVocr6lHn5t2m5ZU0JsmgMopbkNyB/DG1zjSq1DFHg2CfrI8mTjpxpxAFhW7cejaCPBTFcA==">
</form>

input要素になってしまっているからか、turbolinksが悪さしてしまっていたのでdata-turbolinksをfalseに。

ちなみにちなむと、Rubyだとシンボルにはハイフンを使えないみたいなので、button_toのほうではdata: {"turbolinks" => false}みたいな書き方になるんですね。

data-turbolinksの話もうちょいあるので、あとで別記事に落としときたい。


脱線が過ぎましたが、とにかくボタンを押すと前のページに戻るような処理を書いていました。

Chromeではあっさり動作が確認できたのでほっといたのですが、Safariで確認した際、遷移先のスクリプトが動いていないことに気がつく。

⌘ + Rでリロードするとちゃんと動くので、Safariの場合のブラウザバックはもとのページをリロードしないのかな?と推測。


解決策

まず原因から明かしていくと、Back-Forward Cacheなるもののせいであったようです。

javascript - Mobile Safari back button - Stack Overflow

Mobile Safari で戻るボタンを使えなくする (iOS 7) - dunno logs

モバイル版のSafariにおいてよく語られる話のようですが、このページのデモを試してみると、

PC版のSafariでもPageTransitionEvent.persistedがtrueになっていました。

※persisted : 現在みているWebページがキャッシュからロードされていたものかどうか判断する

PageTransitionEvent.persisted - Web APIs | MDN

どうやらこのキャッシュが表示されてしまっている。

ということは、戻った先のページにこのBack-Forward Cacheがあるか判定して、その上でページをリロードする処理をすればよい。

遷移先のページが見えたときイベント発火という処理は、先のデモが掲載されていたページにて解説されている、onpageshowというイベントハンドラが司るとのこと。

Back-Forward Cacheで読み込んだ時にも発火してくれるそうです。

どうやらHTMLでも設定できそうではありますが、キャッシュの有無を判定してあればリロードという実装ならJavaScriptにした方がいいのかな……。となり、

結果jsファイルに以下の記述をしました。

window.onpageshow = function(event) {
  if (event.persisted) {
    location.reload();
  }
}

ここまでjQueryで記述してきたので本当はそれに合わせたかった(実現している記事もある)けどどうにもうまくいかなかったので、

ひとまずここだけ生のJavaScriptになってます……いびつ……。

ただ道理は通っていたようで、無事に遷移先でリロードされるようになりました。

https://i.gyazo.com/b2403c322c73c5da85ffa0ec0a7154c8.gif

一瞬残像が見えるのはご愛嬌(でいいんだろうか)。


ところで、これまでちょくちょく断片的な記事を書いてきたアプリケーションは、実はTECH::EXPERTというプログラミングスクールの課題として制作してきたオリジナルアプリでして。

こちら、10/14までの受講期間中に、どうにかproduction環境で動く形にまで仕上げることができました!

というわけで、ひとまずカリキュラムは修了できたことになるようです。

プログラミング経験と呼べるようなものは無いに等しい、学歴も職歴も誇れるようなものではない、そんな状態から、

夜間休日コースの半年間でWebアプリケーションを自分で設計し実現できるようになるなんて……と感慨深い気持ちでいます。

制作は一人でしたが、けしてひとりきりの力でここまでやり切れたわけではなく、スクールのスタッフの方やスクールを通してできた友人(と私が呼んでいいのかわからないくらいすごいマン)達から知らないことを教えてもらったり、ゆるやかな激励の数々を受けたりしてようやくたどり着けた地平です。

皆様には頭が上がりません。

ここまで書いたからにはアプリを公開したいところなのですが、ドメインつけてもいいんじゃないかとか、見た目や機能の微調整がとか、もう少しだけ詰めたいので、もう少しだけお待ちいただけると幸いです。

製作時に大変だったところとかまとめた記事も書きたい……。


就活のスタートをこのアプリ完成まで待ってもらっていたので、まだまだ、というかこれからが頑張りどころです。

大量の求人票に目を通す作業に戻ります。