Computer >> Máy Tính >  >> Lập trình >> Ruby

Các ứng dụng Rails có rắc JavaScript

Bộ nhớ đệm phân đoạn của Rails tạo ra tốc độ lớn hơn khi một phần lớn hơn của trang được lưu vào bộ nhớ đệm. Điều này khó hơn đối với các trang có nhiều nội dung động hoặc nội dung dành riêng cho người dùng. Một giải pháp là sử dụng “JavaScript rắc”, giống như hagelslag , nhưng không có sô cô la và có thêm yêu cầu tải nội dung dành riêng cho người dùng sau khi phần còn lại của trang được phân phát trực tiếp từ bộ nhớ cache.

Bộ nhớ đệm phân mảnh

Các kỹ thuật như bộ nhớ đệm phân đoạn được sử dụng để tăng tốc độ phản hồi trong ứng dụng Rails bằng cách lưu vào bộ nhớ đệm các đoạn của trang được kết xuất. Bằng cách sử dụng khóa bộ nhớ cache thông minh, các phân đoạn sẽ tự động mất hiệu lực khi nội dung của chúng thay đổi do dữ liệu hiển thị trong chế độ xem được cập nhật.

Các đoạn trong chế độ xem bộ nhớ đệm cung cấp tốc độ tăng lớn hơn từ bộ nhớ đệm nhỏ hơn khi các đoạn được lưu trong bộ đệm được sử dụng thường xuyên hơn. Ví dụ:khi nội dung của trang phụ thuộc vào người dùng hiện đang đăng nhập, việc lưu vào bộ nhớ đệm các đoạn của trang trở nên khó khăn hơn.

Phản hồi chưa đọc

Ví dụ, hãy lấy một blog dựa trên Rails. Trên blog này, mỗi bài viết có thể có một số phản hồi. Một hệ thống xác thực đã được thêm vào để cho phép người dùng đăng nhập và đăng câu trả lời bằng tài khoản của họ. Trên mỗi trang bài viết, chúng tôi liệt kê các phản hồi. Để giúp người dùng của mình dễ dàng hơn, chúng tôi đánh dấu các phản hồi mới bằng biểu tượng và màu nền khác.

Nếu chúng tôi gói mỗi bài viết trong một cache chặn, chúng tôi có nguy cơ đánh dấu các câu trả lời sai là chưa đọc. Khi người dùng yêu cầu trang chỉ mục, phản hồi sẽ được lưu vào bộ nhớ đệm. Khi người dùng khác yêu cầu cùng một trang sau đó, họ sẽ nhận được phân đoạn được lưu trong bộ nhớ cache, với các phản hồi chưa đọc của người dùng đầu tiên.

# 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 %>

Một cách để giải quyết vấn đề này là thêm người dùng hiện đã đăng nhập vào khóa bộ nhớ cache bằng cách sử dụng [@article, @current_user] thay vì chỉ @article khi đối số được truyền vào cache phương pháp trợ giúp.

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

Điều này đảm bảo rằng mỗi người dùng nhìn thấy phản hồi chưa đọc của riêng họ, nhưng phủ nhận hầu hết tốc độ tăng tốc từ bộ nhớ đệm các đoạn, vì các đoạn bài viết hiện được lưu vào bộ nhớ đệm riêng cho từng người dùng.

JavaScript Sprinkles

Vì hầu hết các trang đều giống nhau đối với tất cả người dùng, chúng tôi muốn sử dụng lại phân đoạn bài viết đã lưu trong bộ nhớ cache cho mỗi khách truy cập. Để thực hiện việc này, chúng tôi có thể tải bài viết từ bộ nhớ cache và thêm một yêu cầu bổ sung để tìm nạp nội dung dành riêng cho người dùng sau khi trang được tải thông qua một yêu cầu JavaScript. Sử dụng một loạt các chức năng JavaScript cho việc này có một số lợi thế:

  1. Trang có thể được lưu vào bộ nhớ cache một lần và được sử dụng lại cho những khách chưa được xác thực cũng như những người dùng khác mà không phải lưu các phân đoạn vào bộ nhớ cache riêng cho mọi người dùng.
  2. Nội dung quan trọng nhất được tải trước để có thời gian phản hồi nhanh nhất và các tính năng phụ, như số lượng chưa đọc, được tải sau.
  3. Vì yêu cầu bổ sung được thực hiện thông qua JavaScript nên toàn bộ trang có thể được lưu vào bộ nhớ đệm cạnh trên CDN để cải thiện hơn nữa hiệu suất.

Dọn dẹp

Trước tiên, chúng tôi sẽ xóa nội dung động khỏi các trang của mình để giúp chúng lưu vào bộ nhớ cache dễ dàng hơn. Chúng tôi sẽ xóa @current_user từ khóa bộ nhớ cache trong cache chặn lại, vì vậy chúng không còn được lưu trong bộ nhớ cache cho từng người dùng. Sau đó, chúng tôi sẽ xóa truy vấn tìm số lượng chưa đọc khỏi bộ điều khiển và xóa tên lớp CSS khỏi chế độ xem.

# 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 %>

Chúng tôi còn lại với một trang chung chung dễ lưu vào bộ nhớ cache hơn nhưng thiếu tính năng phản hồi chưa đọc của chúng tôi. Hãy thêm nó trở lại.

Điểm cuối

Trước tiên, chúng tôi sẽ tạo một điểm cuối để tìm các câu trả lời chưa đọc cho người dùng. Chúng tôi muốn thay đổi trạng thái hiện tại của trang sau khi nó được hiển thị, vì vậy chúng tôi sẽ yêu cầu JSON từ nó.

# 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

Điểm cuối của chúng tôi sẽ tạo ra một danh sách các ID phản hồi chưa đọc.

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

Mẹo :Khi tải một thành phần động có thể được hiển thị trước trên máy chủ, việc hiển thị HTML ở phía máy chủ thường nhanh hơn, sau đó đưa trực tiếp HTML vào trang của bạn thông qua JavaScript.

Hiển thị các phản hồi chưa đọc

Thay vì mã hóa cứng URL cho điểm cuối phản hồi chưa đọc trong mã JavaScript, chúng tôi sẽ thêm nó vào thuộc tính dữ liệu trong chế độ xem, vì vậy chúng tôi có thể tham khảo nó sau.

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

Sau khi tải xong trang, chúng tôi sẽ yêu cầu các ID phản hồi chưa đọc từ điểm cuối mới của chúng tôi. Sau đó, chúng tôi sẽ sử dụng dữ liệu từ danh sách đó để đánh dấu từng bài viết là chưa đọc bằng cách thêm một lớp CSS vào đó.

// 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");
        });
      },
    });
  }
});

Vì ứng dụng Rails của chúng tôi sử dụng Turbolinks, chúng tôi sẽ đợi trang được tải bằng cách lắng nghe turbolinks:load biến cố. Khi sự kiện đó kích hoạt, chúng tôi sẽ tìm thấy hộp phản hồi bằng cách sử dụng ID của nó.

Sau đó, chúng tôi sẽ kiểm tra xem phần tử phản hồi có loaded hay không thuộc tính dữ liệu. Chúng tôi sẽ đặt thuộc tính này sau khi cập nhật các câu trả lời chưa đọc sau đó, vì vậy, chúng tôi không đưa ra bất kỳ yêu cầu bổ sung nào trong trường hợp trang được tải lại bằng nút quay lại của trình duyệt.

Trong lần tải đầu tiên, loaded thuộc tính chưa được đặt, vì vậy chúng tôi sẽ tiếp tục thực hiện yêu cầu tới điểm cuối của chúng tôi. Khi thành công, chúng tôi sẽ lặp lại từng bài viết trong kết quả trả về, tìm phần tử của phản hồi theo ID của nó và thêm lớp CSS "chưa đọc" của chúng tôi vào đó.

Rắc!

Bộ nhớ đệm phân mảnh nội dung có thể sử dụng lại và rắc JavaScript vào các trang của bạn để thêm các bit động dành riêng cho người dùng sau này có thể làm cho thời gian phản hồi ban đầu của ứng dụng của bạn nhanh hơn bằng cách phân phát hầu hết nội dung quan trọng trực tiếp từ bộ nhớ cache. Mặc dù phải mất thời gian để thực hiện thêm một yêu cầu và cập nhật trang sau khi nội dung chính đã được tải, nhưng việc trì hoãn nội dung động sẽ khiến ứng dụng của bạn hoạt động nhanh hơn, ngay cả khi yêu cầu đầy đủ mất nhiều thời gian hơn so với việc phân phát mọi thứ, bao gồm cả các phần dành cho người dùng cụ thể, từ bộ nhớ cache.

Để có các thiết lập phức tạp hơn, hãy nhớ xem Stimulus, một thư viện JavaScript bao bọc mô hình rắc vào một khuôn khổ liên kết các chế độ xem HTML với JavaScript của bạn.

Chúng tôi hy vọng bạn thích phần giới thiệu về JavaScript rắc rối trong ứng dụng Rails này. Nếu bạn có bất kỳ nhận xét nào về bài viết này, blog hoặc bất kỳ chủ đề nào khác mà bạn muốn đề cập, vui lòng gửi cho chúng tôi một dòng tại @AppSignal.