Ruby on Railsでリンクで移動した時javascriptが実行されない現象があります。
例えば、$(document).ready
が発火しないという現象。
$(document).ready( xx.. );
みたいなものが動かない。
これは、turbolinksが原因です。
turbolinksとは何なのか?
HTML5のpushStateとajaxを組み合わせてページを高速でレンダリングするための仕組み。
turbolinksを導入するとリンクをクリックした時にGETで取得する全てのページがajaxで処理されるようになる。
(POST、PUT、DELETEの場合はturbolinksを導入していない場合と同じように処理される。)具体的にはページ遷移が発生する時に(これはaタグがクリックされたタイミング)、
htmlのtitleタグの中身とbodyタグの中身をajaxで入れ替え、
ブラウザの現在のURLを遷移先のURLに、戻り先のURLを遷移前のURLに更新する。これによってページ遷移の際にheadタグの中に書かれたJavaScriptとStyleSheetの
パースが行われなくなるので、特にJavaScriptを多用しているサイトではかなりの
高速化になるんじゃないかと。
ただこれは、JavaScriptとStyleSheetがアセットコンパイルされて
どのページでも常に同じファイルを読み込むようになっているという前提なので、
ページごとに異なるJavaScriptやStyleSheetを利用するようになっている場合は、
そもそもturbolinksの導入には向いていない。ajax単体で同様のことを実現しようとした場合、
ajaxではURLは変えられないので、同じURLが複数のコンテンツを指し示したり、
複数のURLが同一のコンテンツを指し示すっていうダサい感じになるが、turbolinksを使うと、HTML5のpushStateを使ってブラウザの履歴を更新出来るので、
ajaxでページを更新したタイミングでURL(ブラウザの履歴)も更新されて、イケてる感じになる。また、JavaScriptやHTML5が使えない場合は従来通りのページ遷移を行う。
turbolinksのページに解決策が示されていて、別途jquery-turbolinksを導入すれば解決する。
Gemfileに
gem 'jquery-turbolinks'
を追記して、bundle install
とかbundle update
する。
Rails5でのturbolinksの挙動
今までのイベント
$(document).on 'page:before-change' , -> console.log 'page:before-change'
$(document).on 'page:fetch' , -> console.log 'page:fetch'
$(document).on 'page:receive' , -> console.log 'page:receive'
$(document).on 'page:change' , -> console.log 'page:change'
$(document).on 'page:update' , -> console.log 'page:update'
$(document).on 'page:load' , -> console.log 'page:load'
$(document).on 'ready page:load' , -> console.log 'ready and load'
$(document).ready -> console.log '$(document).ready in assets'
$(window).on 'load' , -> console.log '$(window).load in assets'
これでJSが発火してくれていたが、、、
Rails5でのイベント
# ページ切り替え時(初回ページも対象)
$(document).on 'turbolinks:load', -> console.log 'turbolinks:load'
# ページ切り替え時(初回ページは対象外)
$(document).on 'turbolinks:render', -> console.log 'turbolinks:render'
# ページ遷移前
$(document).on 'turbolinks:request-start', -> console.log 'turbolinks:request-start'
これで発火するように変わってた。
当面はこの3つだけ知っていれば問題ないかなと思います。