Rails with Hotwired – render siêu tốc mà không cần code 1 dòng JavaScript nào

Mở đầu Tản mạn về lịch sử 1 chút.. Có lẽ mọi người đã biết, Rails là 1 frame-work tương đôí mạnh mẽ trong việc phát triển 1 web app và thường được phát triển theo mô hình truyền thống MVC. Cách hoạt động thường là client gửi request tới server, server xử lý request

Mở đầu

Tản mạn về lịch sử 1 chút..

Có lẽ mọi người đã biết, Rails là 1 frame-work tương đôí mạnh mẽ trong việc phát triển 1 web app và thường được phát triển theo mô hình truyền thống MVC.

Cách hoạt động thường là client gửi request tới server, server xử lý request và response cho client.

Những gì mà client nhận được thường là nội dung của một trang web hoàn chỉnh với HTML, CSS, JS.

Nói tóm lại, server gần như làm tất cả mọi thứ, Client chỉ việc nhận kết quả.

Tuy nhiên, càng ngày, người ta càng đặt trải nghiệm ngươì dùng lên hàng đầu dẫn đến SSR trở nên không đáp ứng được do SSR là tập trung xử lý ở server, trong khi trải nghiệm người dùng thì tập trung xử lý ở client.

jquery hay Ajax dần được sử dụng rộng rãi vơí khả năng cho phép load những content DOM cần thiết, còn các thành phần khác của page thì vẫn giữ nguyên như cũ. Nhờ đó tốc độ và trải nghiệm của người dùng được tăng lên đáng kể

Kế tiếp đó là sự bùng nổ của SPA vơí sự tách biệt hoàn toàn giữa FE và BE

Tuy nhiên điểm chung của các giaỉ pháp bên trên vẫn là những đoạn code JS dài lê thê. Và 1 số các hạn chế về SEO, đánh index

Vậy có 1 giải pháp thay thế, chúng ta hoàn toàn có thể làm được những điều tương tự vơí code Rails thuần. Bạn gần như không phải code bất kì dòng JS nào vơí Hotwired 😄

Hotwired

Hotwire là một cách tiếp cận xây dựng web mà không cần code JavaScript bằng cách gửi HTML trực tiếp thay vì JSON

Điều này làm cho lần load trang luôn nhanh chóng, tăng trải nghiệm cả người dùng lẫn người code =))

Trái tim của Hotwire là Turbo.

Nó là một tập hợp các kỹ thuật bổ sung giúp tăng tốc độ điều hướng các trang, chia các trang phức tạp thành các thành phần và render từng phần thông qua WebSocket ( ActionCable, cchannels, streaming data).

Bạn có thể tìm hiểu thêm về Turbo ở đây https://turbo.hotwired.dev/handbook/drive

Hotwire sử dụng server-side-rendering (SSR). Điều này khiên nó không những duy trì được ưu điểm về mặt tốc độ (giống như SPA làm được) mà còn giúp giải quyết một số vấn đề về SEO, ví dụ như lập chỉ mục (index).

Áp dụng Hotwired

Mình sẽ implement thử 1 Rails app sử dụng Hotwired để hiểu rõ hơn cách hoạt động của nó (Ở đây mình dùng Rails 6.1 và ruby 2.7.2)

Ở đây chúng ta sẽ demo vơí 1 app nhỏ bao gồm các Post. Với môĩ Post thì có thể like/ edit Post đó

Tạo project

rails new hotwire-test

cd hotwire-test

Setup gem file

Add gem to Gemfile

# Use Redis adapter to run Action Cable 
gem 'redis','~> 4.0'

gem "hotwire-rails","~> 0.1.0"

Sau đó bundle

bundle install
rails hotwire:install

Config actioncable

vim config/cable.yml

development:
  adapter: redis
  url: redis://localhost:6379/1

Generate Model

rails g scaffold posts body:text likes_count:integer

Migrate database

rails db:create db:migrate

Implement logic

routes.rb

Rails.application.routes.draw do
  resources :postsdo
    resource :likeend
  root to:"posts#index"end

posts_controller

classPostsController<ApplicationController
  before_action :set_post, only:[:show,:edit,:update,:destroy]defindex@posts=Post.all
    @post=Post.newenddefshow;enddefnew@post=Post.newenddefedit;enddefcreate@post=Post.new(post_params)@post.save
  enddefupdate@post.update(post_params)endprivatedefset_post@post=Post.find(params[:id])end# Only allow a list of trusted parameters through.defpost_params
      params.require(:post).permit(:body,:likes_count,:reposts_count)endend

post/index.html.erb

<pid="notice"><%= notice %></p><h1>Posts</h1>

<%= turbo_stream_from "posts" %>

<%= turbo_frame_tag "post_form" do %>
    <%= form_with(model: post, id: dom_id(post)) do |form| %>
      <divclass="field">
        <%= form.label :body %>
        <%= form.text_area :body %>
      </div><divclass="actions">
        <%= form.submit %>
      </div>
    <% end %>
<% end %>

<%= turbo_frame_tag "posts" do %>
    <%= turbo_frame_tag dom_id(post) do %>
      <divclass="card card-body"><div><%= post.body %></div><divclass="mt-2">
          <%= button_to "Likes (#{post.likes_count})", post_like_path(post), method: :post %>

          <%= link_to "Edit", edit_post_path(post) %>
        </div></div>
    <% end %>
<% end %>

Ở đây chúng ta sử dụng đến kỹ thuật turbo_frame_tag, khi render HTML sẽ dưới dạng tag <turbo-frame>.

Đây là method của Turbo frame helper, sử dụng tham số id để phân biệt các thành phần DOM nào cần update (trong trường hợp này là “posts”)

model/post.rb

classPost<ApplicationRecord
  after_create_commit { broadcast_prepend_to "posts"}
  after_update_commit { broadcast_replace_to "posts"}

  validates :body, presence:trueend

Việc xử lí broadcast mình có thể xử lí trong controller. Phần này ae có thể tìm hiểu thêm nhé. Ở đây thì mình để trong model luôn

Kết quả

View

Check Log

Turbo::StreamsChannel transmitting "<turbo-stream action="replace" target="post_9"><template><turbo-frame id="post_9">n  <div class="card card-body">n    <div>Hello W GGGGGGGG OKla</div>nn    <div class="mt-2">n      <form class="button_to" method="post" action="/posts/9/like"><input type="submit" value=...(via streamed from posts)

Work Like a Charm (magic) 😄

Tài liệu tham khảo

https://github.com/hotwired/hotwire-rails

https://gorails.com/series/hotwire-rails

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ