2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
リンクをコピー
記事をブックマーク
前島真一氏:Turbo Streamsとは何かと言うと、下の図のようなHTML片をサーバーサイドからTurbo StreamsのContent-Typeで返してあげると、TurboがこのHTMLの内容を見て、いい感じに解釈して処理をしてくれるというものです。
いい感じに解釈するというのはどういうことかこのturbo-streamタグを使って説明しますね。turbo-streamタグにtarget属性があって、これはmessagesです。actionでそこに対して何をするかを書きます。これはmessagesでappendなので、ここのtemplateの中であるDOMをmessagesなidのDOMの中に挿入するという指示になります。
turbo-railsというgemを使うともうちょっと簡単にさっきのHTMLを構成できます。ここですね、turbo-railsを使うと、こんな感じでさっきのHTML片を作ることができます。
render turbo_stream : turbo-stream.append( : messages, # ゴニョゴニョ……)みたいな感じですね。このパーシャル以降は元となる部分テンプレートを指定します。さらにその部分テンプレートに対してturbo-streamタグや、テンプレートタグをここのヘルパーメソッドで追加して返してくれます。
なので、手動でturbo-streamタグを作る必要はないということですね。既存のmessagesを表現する部分テンプレートをそのまま活用して、Turbo Streamsを使うことができるということです。
今、appendするという操作だけを書きましたが、一度のリクエストやレスポンスで複数の操作をしたいケースもあると思います。この例はentry.turbo_stream.erbなんですが、この中に複数の処理を書くと……entryをremoveして、さらにappendするということが一度にできます。
さっきも話したとおり、actionとして使えるのはappend、prepend、replace、update、removeの5種類に限られています。SJRを使う場合と比べてできることは限られているので、考えることが減って楽です。他にもなんでもできるがゆえになんでもやってしまって、セキュリティに穴を開けてしまうことを防げるのがTurbo Streamsのメリットかなと思います。
Turbo Streamsのメリットはもう1つあって、それはwebsocketで効果的に使えるということです。Action Cable用のヘルパーメソッドがあって、Turbo Streams用のチャンネルのsubscribeやbroadcastが簡単にできます。
メールサービスでメール一覧を表示しているときに新着メールが届くことがあると思いますが、そのときにページをリロードせずに自動的に新しいメールをピュッと表示することが簡単に作れる感じですね。
このヘルパーメソッドがどうなっているのかは、ドキュメントにはあんまり書かれていないので、現時点ではソースコードを見る必要があります。
ここまでTurbo DriveとTurbo Streamsについて説明しました。Turbo Driveは、既存のHTMLをそのまま使いつつ、ユーザー体験を良くできるのがいいところです。Turbo Streamsのいいところの1つとして、同じテンプレートをいろいろなところで使い回せるというのがあります。
さっきの例で、一通のメッセージを表す部分のテンプレートをTurbo Streamsでも使えるというのがありました。
この使い回すというところをもっとやりたいじゃないですか。例えばスマホなどの小さい画面とPCなどの大きい画面があります。小さい画面と大きい画面で1つのテンプレートを使いたいというときにTurbo Framesが使えます。
Turbo Framesとは何かを説明します。turbo-frameタグがあります。このturbo-frameというタグの中身は、特別なframeとして区切られます。iframeとは別で、内部的なframeとして区切られます。このframe内のリンクはTurbo Frames用のリンクです。
このHTML自体はメッセージ一覧があって、個別のメッセージもズラッと表示されていると考えてください。ここでは1つしか表示されていないですけどね。
messageがあって、それを編集するためのリンクがあります。次のページのURLにアクセスしたときに返すHTMLがこれだとします。この中にもturbo-frameタグがありますね。idはさっきのturbo-frameのidと同じです。一覧ページの編集リンクを押すと、turbo-frameタグの中身だけが抜き出されて、さっきのturbo-frameタグの中身と差し替わります。
h1タグのところは無視されます。ここにmessage/1/editというURLがあります。ここに直接アクセスすると、ページが普通にレンダリングされます。このh1のメッセージの編集というのも含みます。
つまり、Turbo Driveはボディタグを全部差し替えるというもので、Turbo Framesを使うとレスポンスのHTMLのうちの一部を使って、元のHTMLの一部を部分的に差し替えることができるということです。
turbo-frameのリンク全部がそうだと困るというケースも当然あるので、そういうときには、target="_top"みたいなものを書くと、ここのframeのリンクは普通のTurboのリンクとなって、ボディタグ全体が書き替わります。
このtarget="_top"をうまく使い分けると、1つのテンプレートを使い回すのがやりやすくなります。例えばPCなどの大きいディスプレイを使ったときには一覧ページの中で編集をすることを簡単に実装できます。
一方でスマホのような小さい画面の中で、一覧ページで編集するのはなかなか大変ですよね。そういうときは専用のedit用のページに遷移させて、その中で編集できます。
Turbo Framesの便利な点はもう1つあります。srcという属性をつけることができることです。例では/maybe_friendsというのがありますが、このページが表示されたあとのタイミングで、ここ(maybe_friends)のURLにアクセスして、ここの返すHTMLの中のturbo-frameタグの中身が差し替えられます。結果、レンダリングにかかる時間を省略して、ページ全体を表示できて、ページの表示が早くなります。
このloading="lazy"は、DOMが画面に表示されるまで/maybe_friendsへのアクセスを遅延させるというやり方です。例えばturbo-frameタグが画面のすごく下のほうにあって、ファーストビューでは見えなければ、そこは表示しなくてもいいかもしれないですよね。もし表示しなかったら、その分マシンリソースの節約になります。こういう感じで、便利に使えるかなと思います。
ここまででTurbo Framesの説明は終わりで、ここからは最後のTurboですね。Turbo Nativeというものがあります。これはiOSやAndroidでTurboを使うためのライブラリです。iOSやAndroidでTurboを使うときは、webviewでアプリケーションを利用します。
Turbo Driveで画面遷移したときは、単にボディタグを差し替えるだけじゃなくて、ページを遷移した履歴も操作しているんですね。それをブラウザだけじゃなくて、iOSやAndroidでの画面遷移としても反映させるために使われるもので、機能としてそれ以上の特別なものがあるわけではないです。
そういう感じで、Turboについて一通り話をしました。冒頭から何回も言っているとおり、Hotwireを使うとサーバーサイドにロジックが集中して、jsの量はその分減ります。ただ、jsがまったくのゼロになることは今どきのアプリケーションを作っている限りはないですよね。
Turboを使うと、jsやCSSを最初のリクエストのレスポンスとして、全部返すという形式を取るのが基本的な戦略になると思います。そうすると、どこになんのjsを置くのかというのが難しくなってきます。さらに、特定のページだけでjsを実行させたいというのを実装するのが大変になります。if文がいっぱい入ってくるんですね。
そういったことを解決するフレームワークとして、Hotwireの1つであるStimulusが活躍します。これはすごく簡単に説明すると、HTMLとjsをいい感じに紐づけあって整理するライブラリです。個人的には学習コストが低いのが気に入っています。
公式ページからスクリーンショットを撮ってきたものです。これをもとにして説明します。ここにinputタグがあって、willnetと入力してGreetボタンを押すと、ここにHello,willnet! と出てきます。
これは左側のHTMLと右側のjsで構成されています。左側のHTMLを見てみると、data-controllerとかdata-hello-targetとか、dataなんとかという属性がいっぱいあります。これがStimulusに関係している属性です。
この一番上のdivがdata-controller="hello"となっています。Stimulusはこれを見て、hello.controller.jsと紐づいていると判断して、ここのjsを見にいきます。このControllerを継承しているクラスがあるのを見にいきます。
次に左側のHTMLのbuttonのところですね。data-action="click->hello#greet"という属性がついています。ここのDOMをクリックすると、hello_controllerのgreetメソッドを実行する指示です。
つまり右側のgreetメソッドが実行されます。greetメソッドの中にはoutputTargetやnameTargetというプロパティがあって、これはstatic変数で定義されているnameとoutputから自動で生成されているプロパティです。
outputTargetはspanタグのdata-hello-target="output"というDOMと結びついています。右のnameTargetも同様ですね。上のinputタグのdata-hello-target="name"と紐づいています。
ここにwillnetが入っていって、結果として、Hello,willnet! が、ここのoutputTargetのtextContentとして入ってくる流れです。これがStimulusの基本的な機能です。すごくわかりやすいと思いませんか? もうだいたいわかった感じですよね。
あともう1つStimulusの便利ポイントがあって、特定のページだけで発火させたいjsが書きやすいというのがあります。hello-controllerの中でconnectというメソッドを用意しておくと、hello_controllerに紐づいている属性のDOMが表示されたときに、自動的にここの処理が実行されます。
これがあると、特定のページでだけ実行させるのが簡単に書けます。
Stimulusのメリットは、controllerごとにファイルが自然と分かれて整理されることです。さらにHTMLタグの属性名を見ると、それがjsのどのファイルのどの場所、どのプロパティと紐づいているのかがすぐにわかります。
特定のページでだけ発火させたいjsが簡単に書けます。
TurboとStimulusに関して一通り話をしました。
Hotwireについてまとめると、最小限の労力でユーザーが求めているサービスを提供することに特化しているライブラリだと思います。それはつまり、サーバーサイドでいうRailsですよね。それをフロントエンド側にも持ちこんだと言えると思います。
なので少人数で、どういう方針でサービスを成長させていくのか、開発しつつマーケットにフィットするかを試すようなスタートアップに一番適しているのかなと思います。さらに中規模くらいのサービスであれば、普通に使えると思っています。
すごく便利なので、みなさんも今回の機会に使ってみたらどうでしょうか? ちょっと長くなりましたが以上です。ご清聴ありがとうございました。
関連タグ:
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2024.11.15
好きなことで起業、赤字を膨らませても引くに引けない理由 倒産リスクが一気に高まる、起業でありがちな失敗