サーバから見たTurbo FramesとTurbo Streamsの違い

Turbo Framesは画面の一箇所のみを変更するのに対して、Turbo Streamsは複数箇所を変更したり、更新方法を細かく指定したりできます。通常はこれを基準に使い分けます。

ただしもう一つ使い分け方の基準があります。Turbo Framesはクライアント側で制御されるのに対して、Turbo Streamsはサーバ側で制御できることが必要な場合です。

なおこの点については、実例を使って解説しています

  • Turbo Framesはリクエストを送信時にクライアント側でレスポンスの処理方法を指定します
    • <turbo-frame id="hoge">...</div>に囲まれた箇所からリクエストを送信すれば、レスポンスにも対応する<turbo-frame id="hoge">...</div> (idが"hoge")が存在することが期待され、その中だけが取り出されて画面の更新に使用されます。
    • 他にも<a>タグ、もしくは<form>タグにdata-turbo-frame属性をつけて、対象の<turbo-frame>を指定したり、JavaScriptでTurbo.visit([url], {frame: [turbo-frame名]})を呼び出す方法でTurbo Framesを使用する方法もありますが、いずれもクライアント側でレスポンスの処理方法を指定します。
    • レスポンスに対応するTurbo Frameが見つからない場合はturbo:frame-missingイベントが発火しますので、やはりクライアント側で対処します。
  • Turbo Streamsはサーバ側だけでレスポンスの処理方法を指定します
    • Turbo Streamsレスポンスはサーバだけが決めます。レスポンスが下記の項目を満たせば、Turbo Streamsとして処理されます。
      • レスポンスヘッダーにContent-Type: text/vnd.turbo-stream.html;をつけます。これはクライアントに対して、「Turbo Streamsとして処理しなさい」の合図になります。
      • レスポンスbodyに<turbo-stream action="[アクション名]" target="[ターゲット名]">を返します。サーバ側でDOMのどの箇所(target)に対してどのような変更(action)を加えるかを明示します。クライアントはこれに従います。
    • 必須ではありませんが、クライアント側からリクエスト時にAccept: text/vnd.turbo-stream.html;ヘッダーをつけることもできます。これはサーバの処理を助けるものであり、Turbo Streamsそのものの動作には影響ありません。<form>タグからのPOST/PUT/PATCH/DELETEリクエストには自動的にこのヘッダーが付きますが、それ以外のリクエストでこのヘッダーを自動的につけたい場合はdata-turbo-stream属性を使います。
  • Turbo FramesとTurbo Streamsの双方を使用した場合はTurbo Streamsの方が優先します。

具体的な使用場面

  • 通常は画面の1箇所だけを更新するときはTurbo Framesを使います。同時に複数箇所を更新するとき、もしく更新方法を細かく指定したい場合はTurbo Streamsを使います。
    • ただし複数箇所を更新する場合でも、更新範囲を大きくとれば1箇所の更新で済むこともあります。
    • morphingを使うと画面のステートが保持されますので、更新範囲が大きくなってもUXを損なう心配がありません。(morphingはTurbo Drive, Turbo Frames, Turbo Streamsのいずれでも使用できます)
  • サーバ側のレスポンスによって画面更新方法を切り替えたい場合はTurbo Streamsが使いやすいです。
    • サーバでしか実行できない複雑なバリデーションがあり、かつその結果によって画面更新方法を変えたい場合があります。このようなときは、レスポンス方法をサーバ側で指定できるTurbo Streamsが便利です。
    • なお別方法としてturbo:submit-endイベントのレスポンスステータスを確認して、画面更新方法を切り替えることもできます。この場合はTurbo Streamsを使わずに、turbo:submit-endのイベントハンドラ(クライアント側)の中で処理を記述します。