2024.10.01
自社の社内情報を未来の“ゴミ”にしないための備え 「情報量が多すぎる」時代がもたらす課題とは?
リンクをコピー
記事をブックマーク
前島真一氏: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.10.29
5〜10万円の低単価案件の受注をやめたら労働生産性が劇的に向上 相見積もり案件には提案書を出さないことで見えた“意外な効果”
2024.10.24
パワポ資料の「手戻り」が多すぎる問題の解消法 資料作成のプロが語る、修正の無限ループから抜け出す4つのコツ
2024.10.28
スキル重視の採用を続けた結果、早期離職が増え社員が1人に… 下半期の退職者ゼロを達成した「関係の質」向上の取り組み
2024.10.22
気づかぬうちに評価を下げる「ダメな口癖」3選 デキる人はやっている、上司の指摘に対する上手な返し方
2024.10.24
リスクを取らない人が多い日本は、むしろ稼ぐチャンス? 日本のGDP4位転落の今、個人に必要なマインドとは
2024.10.23
「初任給40万円時代」が、比較的早いうちにやってくる? これから淘汰される会社・生き残る会社の分かれ目
2024.10.23
「どうしてもあなたから買いたい」と言われる営業になるには 『無敗営業』著者が教える、納得感を高める商談の進め方
2024.10.28
“力を抜くこと”がリーダーにとって重要な理由 「人間の達人」タモリさんから学んだ自然体の大切さ
2024.10.29
「テスラの何がすごいのか」がわからない学生たち 起業率2年連続日本一の大学で「Appleのフレームワーク」を教えるわけ
2024.10.30
職場にいる「困った部下」への対処法 上司・部下間で生まれる“常識のズレ”を解消するには