RailsでのHotwireの使用
JavaScriptコードを記述せずに、ページの変更とフォームの送信を高速化し、複雑なページをコンポーネントに分割する方法を探している場合、この投稿はRailsをHotwireで次のレベルに引き上げるのに役立ちます。この記事では、サーバー側のレンダリングにツールを使用する方法を説明します。
Hotwireとは何ですか?
Hotwireは、JSONの代わりにHTMLをネットワーク経由で送信することにより、JavaScriptを記述せずに最新のWebアプリケーションを構築する方法を提供します。これにより、ページの読み込みが速くなります。 Railsは、従来のシングルページアプリケーション(SPA)に関連する速度や応答性を犠牲にすることなく、常にテクノロジーに組み込まれているため、サーバー側でのレンダリングを維持し、よりシンプルで生産性の高い開発エクスペリエンスを実現します。
Hotwireのコアはターボジェムです。これは、ページのナビゲーションとフォームの送信を高速化し、複雑なページをコンポーネントに分割し、WebSocket(ActionCable、チャネル、ストリーミングデータで構成される)を介してページの部分的な更新を送信する一連の補完的な手法です。
>なぜそれを使用する必要があるのですか?
JavaScriptに苦労していて、ページ間をはるかに高速に移動する感覚でユーザーエクスペリエンスを向上させたい場合は、Hotwireが代わりになります。
Hotwireはどのように機能しますか? Hotwireは、サーバー側レンダリング(SSR)を使用して、SPAの主な利点を維持しながら、SPAに関連する問題のいくつかを解決します。 SSRはレンダリングプロセスを逆にし、従来の読み込みと同様に、SPAレンダリング作業の一部をサーバーにもたらします。 SSRは、レンダリングの一部がサーバー上で行われるため、ユーザーにアプリケーションのより効率的なロードを提供できます。パフォーマンスを向上させる可能性に加えて、インデックス作成などのSEOの問題に対処するのに役立ちます。
使い方は簡単ですか?
使い方はとても簡単です。 Railsプロジェクトのデフォルトパッケージ(Ruby、RoR、ActionCable、WebSocket)、すべてのJS依存関係をダウンロードするTurbo gem、およびWebSocketの閲覧中に一時データを保存するRedisが必要です。
TurboはTurboDrive、Frames、Streams、およびNativeによって補完されるため、単一ページのWebアプリケーションの速度を得るために別の言語(JS)を学ぶ必要はありません。ドライブはリンクとフォームを高速化し、ネットワークをリロードする必要性を減らします。一方、フレームはネットワークをよりロードしやすい独立したコンテキストに分割します。
Railsでどのように使用されますか?
このセクションでは、段階的な例を示します。
この例では、次のものが必要です。
- ルビー
- Ruby on Rails
- Redis
- SQLite(デフォルトのデータベース)
- ジェムホットワイヤー
- TurboRails
- StimulusJS
- WebSocket
- ActionCable
どのプロジェクトを作成しますか?
ソーシャルメディアプロジェクトを作成します。
まず、ターミナルを開きます。新しいRailsプロジェクトから始めましょう:
rails new social-media
プロジェクトを入力してください:
cd social-media
Hotwireジェムをプロジェクトに追加します:
bundle add hotwire-rails
または、Gemfile
を開きます そしてこれを追加します:
gem "hotwire-rails"
2番目のオプションを使用する場合は、今すぐバンドルを実行する必要があります。
bundle install
次に、インストールします。
rails hotwire:install
今こそ、Hotwireが行った初期設定を分析する絶好の機会です。 Gemfileにアクセスすると、次のようになります。
gem 'redis', '~> 4.0'
なぜRedisが必要なのですか?
Redis gemが追加されたのは、ActionCableがWebSocketの閲覧中に一時データを保存するためにRedisgemを必要とするためです。ただし、Redisをインストールするだけでは使用できません。正しく構成されているかどうかを確認する必要があります。 config/cable.yml
に移動すると ファイルの場合、次のようになります。
development:
adapter: redis
redis://localhost:6379/1
アプリケーションを起動するときにRedisが実行されていることを確認してください(redis-server
。
JSの依存関係
package.json
の依存関係を確認してください :
dependencies: {
@hotwired/turbo-rails: ^7.0.0-beta.5,
@rails/actioncable: ^6.0.0,
@rails/activestorage: ^6.0.0,
@rails/ujs: ^6.0.0,
@rails/webpacker: 4.3.0,
stimulus: ^2.0.0
}
すべてのファイルをチェックした後、views
を生成します 、controllers
、models
およびmigrations
posts
の場合 body
を含むテーブル 、およびlikes
列。これを行うには、ターミナルで次のコマンドを実行します。
rails g scaffold posts body:text likes:integer
すべてが生成されたので、これらの変更をデータベースに送信する必要があるため、ターミナルで次のコマンドを実行します。
rails db:create db:migrate
すべてがうまくいけば、サーバーを実行できます(rails server
)そしてすべてがOKかどうかを確認します。そのためには、サーバーを実行してから、posts
にアクセスします。 ページ。https://localhost:3000/posts
になります :
投稿ディレクトリの印刷画面
次に、投稿を一覧表示します。そのために、app/views/posts/_post.html.erb
を作成します ファイルを作成し、それに次のコードを追加します:
<div style="background: lightgrey; width: 300px; padding: 10px;">
<%= post.body %>
<br>
<%= link_to :edit, edit_post_path(post) %>
<%= button_to "likes (#{post.likes || 0})", post_path(post, like: true), method: :put %>
</div>
<br>
本文フィールド(nullにすることはできません)を検証する必要があります。ブロードキャストに、作成後の最初のツイートと同じ画面にツイートを表示するように指示します。これを行うには、ファイルapp/models/post.rb
を編集します 次のコードを挿入します:
class Post < ApplicationRecord
validates_presence_of :body
after_create_commit { broadcast_prepend_to :posts }
end
投稿を注文する必要があるため、コントローラーを開きます(app/controllers/posts_controller.rb
。
...
def index
@posts = Post.all.order(created_at: :desc)
@post = Post.new
end
...
それでは、index
を編集しましょう。 (app/views/posts/index.html.erb
)new post
を表示します ページとすべてのposts
のリスト 。
<%= turbo_stream_from :posts %>
<%= turbo_frame_tag :post_form do %>
<%= render 'posts/form', post: @post %>
<% end %>
<%= turbo_frame_tag :posts do %>
<%= render @posts %>
<% end %>
最後に、create
を変更しましょう コントローラのメソッド。 show post
にリダイレクトされないようにするため ページ、すべてを同じページに保持しましょう。
...
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to posts_path }
format.json { render :show, status: :created, location: @post }
else
format.turbo_stream { render turbo_stream: turbo_stream.replace(@post, partial: 'posts/form', locals: { post: @post }) }
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
...
最終ページは次のようになります:
最終ページの印刷画面
投稿が作成されたら、ターミナルログを確認してください。次のようになります:
[ActionCable] Broadcasting to posts: "<turbo-stream action=\"prepend\" target=\"posts\"><template><div style=\"background: lightgrey; width: 300px; padding: 10px;\">\n first post\n <br>\n <a href=\"/posts/1/edit\">edit</a>\n <form class=\"button_to\" method=\"post\" action=\"/posts/4?like=true\"><input type=\"hidden\" name=\"_method\" value=\"put\" /><input type=\"submit\" value=\"likes (0)\" /><input type=\"hidden\" name=\"authenticity_token\" value=\"<token>==\" /></form>\n</div>\n<br>\n</template></turbo-stream>"
これは、次のように、ActionCableが超高速のパフォーマンスでターボストリームを処理していることを意味します。Completed 302 Found in 18ms
。
Railsサーバーと一緒に実行するために別の実行可能ファイルが必要ですか?
いいえ、ActionCableはUnicorn、Puma、Passengerなどの一般的なサーバーで正常に動作するためです。
HerokuはHotwireをサポートしていますか?
はい、HerokuはHotwire(WebSocket)のベースをサポートしています。さらに質問がある場合は、Herokuの公式ドキュメントを確認してください。
なぜRedisを使用しているのか疑問に思われる場合は、もう1つ理由があります
HerokuをRedisなしで使用すると、アプリが複数のdynoにスケーリングされたときにメッセージがすべてのユーザーに送信されることはありません。現在のアプリはステートレスであるため、最初のdynoに接続されたクライアントは接続されたクライアントからメッセージを送信されません。 2番目のdynoに。 Redisは、メッセージの状態をグローバルストレージに保存することでこの問題を解決します。
HerokuでRedisを設定する
リモートRedisインスタンスとのRedisCLIセッションを確立するには、heroku redis:cli
を使用します 。インスタンスを指定しない場合、REDIS_URL
にあるインスタンス デフォルトで使用されます。複数のインスタンスがある場合は、接続するインスタンスを指定します。
アプリケーションサーバーではどのように機能しますか?
Redis pub-subシステムを使用するように各dynoを設定する必要があります。すべてのdynoは同じチャネル(デフォルト)にサブスクライブし、メッセージを待機します。各サーバーがメッセージを受信すると、接続されているクライアントにメッセージを公開できます。 subscribe
について説明します 別のスレッドで、subscribe
はブロッキング機能であるため、メッセージを待機すると実行フローが停止します。さらに、接続でサブスクライブコマンドが実行されると、接続はサブスクライブを解除するかメッセージを受信することしかできないため、2番目のRedis接続が必要です。スケーリングの詳細については、こちらをご覧ください。
現在、アプリケーションは公開されており、多くの攻撃に対して脆弱です。WSSを設定し、入力をサニタイズしてください。 WebSocketセキュリティの詳細についてはこちらをご覧ください。
ここに示したように、新しいアプリケーションを介してHotwireを使用することは可能ですが、Turbolinksから更新することも可能です。
この記事は、「魔法のフレームワーク」がどのように機能するかを理解するのに役立つはずです。その中で、実際には、WebSocketを介した操作とナビゲーションを備えた集約されたターボストリームを介してリクエストを表示する小さなシンプルなアプリケーションを開発する可能性がありました。
-
RailsでのTailwindCSSの使用
CSSは魔法のようですが、時間がかかります。美しく、機能的で、アクセスしやすいサイトを使用するのは楽しいことですが、独自のCSSを作成するのは大変です。 Bootstrapなどの多くのCSSライブラリは近年爆発的に増加しており、Tailwindは2021年にパックをリードしています。 RailsにはTailwindが付属していませんが、この記事では、TailwindCSSを新しいRubyon Railsプロジェクトに追加する方法を説明します。これにより、設計の実装にかかる時間を節約できます。また、Tailwindのユーティリティクラスを使用した設計のウォークスルーも行います。このチュートリア
-
Rails5でのAngularの使用
あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた