কম্পিউটার টিউটোরিয়াল

জাভাস্ক্রিপ্ট স্প্রিঙ্কলস দিয়ে রেইলস স্পিড বাড়ান ডাইনামিক কন্টেন্টের জন্য

রেইলসের ফ্র্যাগমেন্ট ক্যাশিং তখন বড় স্পিডআপ দেয় যখন পেজের বড় অংশ ক্যাশ করা হয়। এটি ডাইনামিক বা ইউজার-স্পেসিফিক কন্টেন্টবিশিষ্ট পেজের জন্য আরও কঠিন। একটি সমাধান হলো "জাভাস্ক্রিপ্ট স্প্রিঙ্কলস" ব্যবহার করা, যা হেগেলস্লাগ-এর মতো, কিন্তু চকলেট ছাড়া এবং বাকি পেজ ক্যাশ থেকে সরাসরি সার্ভ হওয়ার পর ইউজার-স্পেসিফিক কন্টেন্ট লোড করার জন্য এক্সট্রা রিকোয়েস্টসহ।

ফ্র্যাগমেন্ট ক্যাশিং

ফ্র্যাগমেন্ট ক্যাশিং এর মত টেকনিক রেইলস অ্যাপ্লিকেশনে রেসপন্স স্পিড আপ করতে ব্যবহৃত হয় রেন্ডার্ড পেজের ফ্র্যাগমেন্ট ক্যাশ করে। স্মার্ট ক্যাশ কী ব্যবহার করে, ফ্র্যাগমেন্টগুলো অটোমেটিক্যালি ইনভ্যালিডেট হয় যখন তাদের কন্টেন্ট পরিবর্তন হয় কারণ ভিউতে দেখানো ডেটা আপডেট হয়।

ভিউ ফ্র্যাগমেন্ট ক্যাশ করা তখন বড় স্পিড বুস্ট দেয় ছোট ক্যাশ থেকে যখন ক্যাশড ফ্র্যাগমেন্টগুলো আরও বেশি ব্যবহৃত হয়। যখন পেজের কন্টেন্ট বর্তমানে সাইন-ইন করা ইউজারের ওপর নির্ভর করে, উদাহরণস্বরূপ, পেজের ফ্র্যাগমেন্ট ক্যাশ করা আরও কঠিন হয়।

আনরিড রেসপন্স

উদাহরণস্বরূপ, একটি রেইলস-ভিত্তিক ব্লগ নিই। এই ব্লগে, প্রতিটি আর্টিকেলের কিছু রেসপন্স থাকতে পারে। একটি অথেন্টিকেশন সিস্টেম যোগ করা হয়েছে যাতে ইউজাররা সাইন ইন করে তাদের অ্যাকাউন্ট দিয়ে রেসপন্স পোস্ট করতে পারে। প্রতিটি আর্টিকেল পেজে, আমরা রেসপন্সগুলো লিস্ট করি। আমাদের ইউজারদের সুবিধার জন্য, আমরা নতুন রেসপন্সগুলো একটি আইকন এবং ভিন্ন ব্যাকগ্রাউন্ড কালারের সাথে মার্ক করি।

আমরা যদি প্রতিটি আর্টিকেলকে একটি cache ব্লকে র‍্যাপ করি, আমরা ভুল রেসপন্সকে আনরিড হিসেবে মার্ক করার রিস্কে পড়ি। যখন একজন ইউজার ইনডেক্স পেজ রিকোয়েস্ট করে, রেসপন্স ক্যাশ হয়। যখন অন্য একজন ইউজার পরে একই পেজ রিকোয়েস্ট করে, তারা ক্যাশড ফ্র্যাগমেন্ট পাবে, প্রথম ইউজারের আনরিড রেসপন্সসহ।

# app/views/articles/show.html.erb
<%= cache(@article) do %>
  

<%= @article.title %>

<%= simple_format(@article.content) %>

Responses

<% @article.responses.each do |response| %>
<%= time_tag(response.created_at) %> <%= response.name %>: <%= response.content %>
<% end %>
<% end %>

এটি সমাধান করার একটি উপায় হলো বর্তমানে সাইন-ইন করা ইউজারকে ক্যাশ কীতে যোগ করা [@article, @current_user] ব্যবহার করে শুধু @article-এর বদলে cache হেল্পার মেথডে পাস করা আর্গুমেন্ট হিসেবে।

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

<%= @article.title %>

# ... <% end %>

এটি নিশ্চিত করে প্রতিটি ইউজার তাদের নিজস্ব আনরিড রেসপন্স দেখছে, কিন্তু ক্যাশিং ফ্র্যাগমেন্ট থেকে অধিকাংশ স্পিডআপ নিশ্চেষ্ট করে দেয়, কারণ আর্টিকেল ফ্র্যাগমেন্টগুলো এখন প্রতিটি ইউজারের জন্য আলাদাভাবে ক্যাশ হচ্ছে।

জাভাস্ক্রিপ্ট স্প্রিঙ্কলস

যেহেতু পেজের অধিকাংশ অংশ সব ইউজারের জন্য একই, আমরা ক্যাশড আর্টিকেল ফ্র্যাগমেন্টটি প্রতিটি ভিজিটরের জন্য রিয়ুজ করতে চাই। এটি করতে, আমরা আর্টিকেলটি ক্যাশ থেকে লোড করতে পারি এবং পেজ লোড হওয়ার পর একটি জাভাস্ক্রিপ্ট রিকোয়েস্ট দিয়ে ইউজার-স্পেসিফিক কন্টেন্ট ফেচ করতে পারি। এই কাজে জাভাস্ক্রিপ্ট ফাংশনালিটির একটি স্প্রিঙ্কল ব্যবহার করার কয়েকটি সুবিধা আছে:

  1. পেজটি একবার ক্যাশ করা যায় এবং অনঅথেন্টিকেটেড গেস্টসহ অন্যান্য ইউজারদের জন্য রিয়ুজ করা যায় প্রতিটি ইউজারের জন্য আলাদাভাবে ফ্র্যাগমেন্ট ক্যাশ করা ছাড়া।
  2. সবচেয়ে গুরুত্বপূর্ণ কন্টেন্টটি প্রথমে লোড হয় স্পিডিয়েস্ট রেসপন্স টাইমের জন্য এবং সেকেন্ডারি ফিচারগুলো, যেমন আনরিড কাউন্ট, পরে লোড হয়।
  3. যেহেতু এক্সট্রা রিকোয়েস্টটি জাভাস্ক্রিপ্ট দিয়ে করা হয়, পুরো পেজ একটি CDN-এ এজ-ক্যাশ করা যায় পারফরম্যান্স আরও উন্নত করতে।

ক্লিনআপ

প্রথমে আমরা ডাইনামিক কন্টেন্ট আমাদের পেজ থেকে সরিয়ে দিব যাতে সেগুলো ক্যাশ করা সহজ হয়। আমরা cache ব্লকে @current_user-কে ক্যাশ কী থেকে আবার সরিয়ে দিব, তাই সেগুলো আর প্রতিটি ইউজারের জন্য ক্যাশ হবena। তারপর, আমরা কন্ট্রোলার থেকে আনরিড কাউন্ট খুঁজে বের করার কোয়ারি সরিয়ে দিব, এবং ভিউ থেকে CSS ক্লাস নামগুলো সরিয়ে দিব।

# app/views/articles/show.html.erb
<%= cache(@article) do %>
  

<%= @article.title %>

<%= simple_format(@article.content) %>

Responses

<% @article.responses.each do |response| %>
<%= time_tag(response.updated_at) %> <%= response.name %>: <%= response.content %>
<% end %>
<% 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

আমাদের এন্ডপয়েন্টটি আনরিড রেসপন্স আইডির একটি লিস্ট প্রোডিউস করবে।

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

টিপ: যখন একটি ডাইনামিক কম্পোনেন্ট লোড করা হয় যা সার্ভার-সাইডে প্রি-রেন্ডার করা যায়, সার্ভার সাইডে HTML রেন্ডারিং করা সাধারণত দ্রুত, তারপর জাভাস্ক্রিপ্ট দিয়ে সরাসরি আপনার পেজে HTML ইনজেক্ট করা।

আনরিড রেসপন্স দেখানো

জাভাস্ক্রিপ্ট কোডে আনরিড রেসপন্স এন্ডপয়েন্টের URL হার্ডকোড করার বদলে, আমরা এটি ভিউতে একটি ডেটা অ্যাট্রিবিউটে যোগ করব, যাতে পরে আমরা এটিকে রেফার করতে পারি।

# app/views/articles/show.html.erb
# ...

পেজ লোডিং সম্পূর্ণ হলে, আমরা আমাদের নতুন এন্ডপয়েন্ট থেকে আনরিড রেসপন্স আইডি রিকোয়েস্ট করব। আমরা তারপর সেই লিস্টের ডেটা ব্যবহার করব প্রতিটি আর্টিকেলকে আনরিড হিসেবে মার্ক করতে একটি 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");
        });
      },
    });
  }
});

যেহেতু আমাদের রেইলস অ্যাপ্লিকেশন Turbolinks ব্যবহার করে, আমরা পেজ লোড হওয়ার জন্য অপেক্ষা করব turbolinks:load ইভেন্ট লিসেন করে। যখন ইভেন্টটি ফায়ার হবে, আমরা এর ID দিয়ে রেসপন্স বক্স খুঁজে বের করব।

আমরা তারপর চেক করব রেসপন্স এলিমেন্টে loaded ডেটা অ্যাট্রিবিউট আছে কিনা। আমরা এই অ্যাট্রিবিউটটি আনরিড রেসপন্স আপডেট করার পর সেট করব, যাতে ব্রাউজারের ব্যাক বাটন ব্যবহার করে পেজ রিলোড হলে কোনো এক্সট্রা রিকোয়েস্ট না হয়।

প্রথম লোডে, loaded অ্যাট্রিবিউট সেট নেই, তাই আমরা এন্ডপয়েন্টে রিকোয়েস্ট করতে থাকব। সাকসেসে, আমরা রিটার্নড রেজাল্টে প্রতিটি আর্টিকেলের ওপর লুপ করব, এর আইডি দিয়ে রেসপন্স এলিমেন্ট খুঁজে বের করব, এবং আমাদের "unread" CSS ক্লাসটি সেটিতে যোগ করব।

স্প্রিঙ্কলস!

ফ্র্যাগমেন্ট ক্যাশিং রিয়ুজেবল কন্টেন্ট এবং আপনার পেজে জাভাস্ক্রিপ্ট স্প্রিঙ্কল করে পরে ইউজার-স্পেসিফিক ডাইনামিক বিট যোগ করলে আপনার অ্যাপের ইনিশিয়াল রেসপন্স টাইম দ্রুত হতে পারে অধিকাংশ গুরুত্বপূর্ণ কন্টেন্ট সরাসরি ক্যাশ থেকে সার্ভ করে। যদিও এক্সট্রা রিকোয়েস্ট করতে এবং মেইন কন্টেন্ট লোড হওয়ার পর পেজ আপডেট করতে সময় লাগে, ডাইনামিক কন্টেন্ট ডিফার করলে আপনার অ্যাপ স্নাপিয়ার লাগবে, এমনকি যখন ফুল রিকোয়েস্ট সবকিছু, ইউজার-স্পেসিফিক পার্টসহ, ক্যাশ থেকে সার্ভ করার চেয়ে বেশি সময় নেয়।

আরো জটিল সেটআপের জন্য, Stimulus চেক আউট করতে ভুলবেন না, একটি জাভাস্ক্রিপ্ট লাইব্রেরি যা স্প্রিঙ্কলস প্যাটার্নকে একটি ফ্রেমওয়ার্কে র‍্যাপ করে যা আপনার HTML ভিউকে আপনার জাভাস্ক্রিপ্টের সাথে টাই করে।

আমরা আশা করি রেইলস অ্যাপ্লিকেশনে জাভাস্ক্রিপ্ট স্প্রিঙ্কলস এর এই পরিচিতিটি আপনার পছন্দে হয়েছে। আপনার যদি এই আর্টিকেল, ব্লগ বা অন্য কোনো টপিক কভার করতে চান সেটা সম্পর্কে কোনো মন্তব্য থাকে, তবে দয়া করে @AppSignal-এ আমাদের লাইন ড্রপ করুন।

  1. রুবি অন রেইলস AWS Lambda-তে ডিপ্লয়: ধাপে ধাপে গাইড

  2. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি

  3. পাওয়ারফুল রুবি CLI টুল বিল্ড করুন: একটি স্টেপ-বাই-স্টেপ গাইড

  4. LIDAR প্রযুক্তির কাটিং-এজ অ্যাপ্লিকেশন অন্বেষণ