Turbolinks 5で使えるオプション機能として、data-turbolinks-permanent
というものがあります。
気になった動機
Rails+Turbolinks+Reactでシステムを組んでいて、Turbolinksでページごとのアセット読み込みは回避できるようになったのですが、Reactがページごとにマウント・アンマウントされるので、「同じものを再生成するコストが無駄」、また「Ajaxでロードするデータを何度も取ってくる必要がある」などの非効率な点があったので、そちらを改善したくなってきました。
そうしたところ、Turbolinksで対応できるとわかったので、取り入れてみた次第です。
data-turbolinks-permanent
とは
Turbolinksで読み込むページ内に、<div id="some-id" data-turbolinks-permanent></div>
のようにdata-turbolinks-permanent
属性を指定したエレメントがあると、Turbolinksによるページ遷移の後も同じエレメントを再利用するようになります。なお、「id
が同じ」ものだけ引き継がれますので、id
の付与は必須となります。
JavaScriptの世界から見た挙動
もちろん、単なるHTMLを持ち越してもそこまで魅力があるわけではないので、主戦場はJavaScriptウィジェット、ということになります。ということで、イベント段階での挙動を見てみると、次のようになっていました。
-
turbolinks:before-render
時点:永続する要素はまだdocument.body
の中にあって、イベントで取ってこられるe.data.newBody
には上書きされる予定のdata-turbolinks-permanent
つきエレメントが残っている -
turbolinks:load
時点:永続する要素も新しいbody
内部へ移動が完了して、それがdocument.body
になっている
実際に何かしらのウィジェットを渡り歩かせるには、JavaScriptでイベントを拾って、以下のような流れで動かすことになると思います。
-
turbolinks:before-render
の段階で新規マウントしようとしたときには、すでに永続的なマウントが行われていればスルーする - すでに永続的にセットされたものについては、
-
turbolinks:before-render
でe.data.newBody
もチェックして、新しいHTMLに存在しなければアンマウントする - ウィジェットから
<body>
を読み取ってなにか処理を行うような場合、turbolinks:render
で正しい<body>
に入ったところで処理を行わせる
-