Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

JavaScriptを散りばめたRailsアプリケーション

Railsのフラグメントキャッシュは、ページの大部分がキャッシュされるときに、より高速化されます。これは、動的またはユーザー固有のコンテンツが多いページではより困難です。解決策は、 hagelslagのような「JavaScriptスプリンクル」を使用することです。 、ただしチョコレートは含まれず、ページの残りの部分がキャッシュから直接提供された後にユーザー固有のコンテンツをロードするための追加のリクエストがあります。

フラグメントキャッシング

フラグメントキャッシングなどの手法は、レンダリングされたページのフラグメントをキャッシングすることにより、Railsアプリケーションでの応答を高速化するために使用されます。スマートキャッシュキーを使用すると、ビューに表示されるデータが更新されるため、コンテンツが変更されたときにフラグメントが自動的に無効になります。

ビューフラグメントをキャッシュすると、キャッシュされたフラグメントがより頻繁に使用されるときに、小さいキャッシュからの速度が大幅に向上します。たとえば、ページのコンテンツが現在サインインしているユーザーに依存している場合、ページのフラグメントのキャッシュはより困難になります。

未読の回答

例として、Railsベースのブログを見てみましょう。このブログでは、各記事に多数の回答を含めることができます。ユーザーが自分のアカウントでサインインして応答を投稿できるようにするために、認証システムが追加されました。各記事のページに、回答を一覧表示します。ユーザーが使いやすいように、新しい応答にはアイコンと異なる背景色でマークを付けています。

各記事をcacheでラップすると ブロックすると、間違った応答を未読としてマークするリスクがあります。ユーザーがインデックスページを要求すると、応答がキャッシュされます。別のユーザーが後で同じページをリクエストすると、最初のユーザーの未読の応答とともに、キャッシュされたフラグメントを受け取ります。

# app/views/articles/show.html.erb
<%= cache(@article) do %>
  <h1><%= @article.title %></h1>
 
  <%= simple_format(@article.content) %>
 
  <section id="responses">
    <h2>Responses</h2>
 
    <% @article.responses.each do |response| %>
      <div class="<%= response.read_by?(@current_user) ? 'read' : 'unread' %>">
        <%= time_tag(response.created_at) %>
        <strong><%= response.name %></strong>: <%= response.content %>
      </div>
    <% end %>
  </section>
<% end %>

これを解決する方法は、[@article, @current_user]を使用して、現在サインインしているユーザーをキャッシュキーに追加することです。 @articleだけでなく cacheに渡される引数として ヘルパーメソッド。

# app/views/articles/show.html.erb
<%= cache([@article, @current_user]) do %>
  <h1><%= @article.title %></h1>
 
  # ...
<% end %>

これにより、各ユーザーに独自の未読応答が表示されますが、記事のフラグメントがユーザーごとに個別にキャッシュされるようになったため、フラグメントのキャッシュによるスピードアップのほとんどが無効になります。

JavaScriptスプリンクル

ほとんどのページはすべてのユーザーで同じであるため、訪問者ごとにキャッシュされた記事のフラグメントを再利用したいと思います。これを行うには、キャッシュから記事を読み込み、JavaScriptリクエストを介してページが読み込まれた後に、ユーザー固有のコンテンツをフェッチするリクエストを追加します。これにJavaScript機能を散在させることには、いくつかの利点があります。

  1. ページは一度キャッシュして、認証されていないゲストだけでなく、他のユーザーにも再利用できます。ユーザーごとにフラグメントを個別にキャッシュする必要はありません。
  2. 応答時間を短縮するために最も重要なコンテンツが最初に読み込まれ、未読カウントなどの2次機能が後で読み込まれます。
  3. 追加のリクエストはJavaScriptを介して行われるため、ページ全体をCDNにエッジキャッシュして、パフォーマンスをさらに向上させることができます。

クリーンアップ

まず、動的コンテンツをページから削除して、キャッシュしやすくします。 @current_userを削除します cacheのキャッシュキーから 再度ブロックするため、ユーザーごとにキャッシュされなくなります。次に、未読カウントを見つけるクエリをコントローラーから削除し、CSSクラス名をビューから削除します。

# app/views/articles/show.html.erb
<%= cache(@article) do %>
  <h1><%= @article.title %></h1>
 
  <%= simple_format(@article.content) %>
 
  <section id="responses">
    <h2>Responses</h2>
 
    <% @article.responses.each do |response| %>
      <div data-response-id="<%= response.id %>">
        <%= time_tag(response.updated_at) %>
        <strong><%= response.name %></strong>: <%= response.content %>
      </div>
    <% end %>
  </section>
<% end %>

キャッシュしやすい一般的なページが残っていますが、未読の応答機能がありません。もう一度追加しましょう。

エンドポイント

まず、エンドポイントを作成して、ユーザーの未読の応答を見つけます。レンダリング後にページの現在の状態を変更したいので、ページからJSONをリクエストします。

# app/controllers/unread_responses_controller.rb
class UnreadResponsesController < ApplicationController
  def index
    @article = Article.find(params[:article_id])
    @responses = @article.unread_responses_for(@current_user)
  end
end
# app/views/unread_responses/index.json.jbuilder
json.array! @responses do |response|
  json.extract! response, :id
end
# config/routes.rb
Rails.application.routes.draw do
  resources :articles do
    resources :responses
    resources :unread_responses
  end
end

エンドポイントは、未読の応答IDのリストを生成します。

# GET /articles/1/unread_responses.json
[{"id":1},{"id":2},{"id":3}]

ヒント :サーバーで事前レンダリングできる動的コンポーネントを読み込む場合、通常はサーバー側でHTMLレンダリングを実行してから、JavaScriptを介して直接ページにHTMLを挿入する方が高速です。

未読の応答を表示する

JavaScriptコードで未読応答エンドポイントのURLをハードコーディングする代わりに、ビューのデータ属性にURLを追加して、後で参照できるようにします。

# app/views/articles/show.html.erb
<section id="responses" data-url="<%= article_unread_responses_path(@article, json: true) %>">
  # ...
</section>

ページの読み込みが完了したら、新しいエンドポイントに未読の応答IDを要求します。次に、そのリストのデータを使用して、CSSクラスを追加することにより、各記事を未読としてマークします。

// app/assets/javascripts/application.js
document.addEventListener("turbolinks:load", function () {
  responses = document.getElementById("responses");
 
  if (!responses.dataset.loaded) {
    Rails.ajax({
      url: responses.dataset.url,
      type: "GET",
      success: function (data) {
        responses.dataset.loaded = true;
 
        data.forEach(function (response) {
          element = document.querySelector(
            "[data-response-id='" + response.id + "']"
          );
          element.classList.add("unread");
        });
      },
    });
  }
});

RailsアプリケーションはTurbolinksを使用しているため、turbolinks:loadをリッスンして、ページが読み込まれるのを待ちます イベント。そのイベントが発生すると、そのIDを使用して応答ボックスが見つかります。

次に、responses要素にloadedがあるかどうかを確認します データ属性。後で未読の応答を更新した後でこの属性を設定するので、ブラウザの戻るボタンを使用してページがリロードされた場合に追加のリクエストを行うことはありません。

最初の読み込み時に、loaded 属性はまだ設定されていないため、引き続きエンドポイントにリクエストを送信します。成功したら、返された結果の各記事をループし、IDで応答の要素を見つけて、「未読」のCSSクラスを追加します。

振りかける!

再利用可能なコンテンツをキャッシュし、JavaScriptをページに散在させて、後でユーザー固有の動的ビットを追加すると、重要なコンテンツのほとんどをキャッシュから直接提供することで、アプリの初期応答時間を短縮できます。メインコンテンツが読み込まれた後、追加のリクエストを実行してページを更新するには時間がかかりますが、動的コンテンツを延期すると、ユーザー固有の部分を含むすべてを提供するよりも完全なリクエストに時間がかかる場合でも、アプリがよりスッキリした感じになります。キャッシュ。

より複雑な設定については、Stimulusを確認してください。Stimulusは、スプリンクルパターンをフレームワークにラップしてHTMLビューをJavaScriptに結び付けるJavaScriptライブラリです。

RailsアプリケーションでのJavaScriptスプリンクルのこの紹介を気に入っていただけたでしょうか。この記事、ブログ、またはその他の取り上げたいトピックについてコメントがある場合は、@AppSignalまでご連絡ください。


  1. Rubyを使用してコマンドラインアプリケーション(CLI)を構築する方法

    多くの人は、RubyがWebアプリケーションではないことを実行できることを忘れています。この記事では、それを改善するのに役立つコマンドラインアプリケーションを構築する方法を紹介したいと思います! 使い慣れているコマンドラインアプリケーションは次のとおりです。 psql rails bundler gem git コマンドラインアプリケーションを構築する方法はたくさんあります。この記事では、そのうちの3つに焦点を当てます。 あなたは学ぶつもりです : ARGVアレイ OptParseライブラリ トールの宝石 始めましょう! RubyARGV定数 コマンドラインア

  2. LIDAR 技術の応用

    ブログ内 “ LIDAR テクノロジーとは何かについてのガイド 」 LIDAR テクノロジの基本を説明するいくつかの事実について説明しました。現在、LIDAR は、高密度で高精度の地理参照空間データを効率的に取得できるため、最も効果的なマッピング方法の 1 つとして知られています。 このブログでは、LIDAR 技術が現在使用されている分野をリストアップしますが、そのプロセスの適切な機能に LIDAR 技術がどの程度付加価値をもたらしたかは信じられないでしょう。 . LIDAR 技術の応用 農業 – LIDAR は、畑の地形図を作成し、農地の傾斜と日当たりを明らかにするこ