Nếu bạn đang tìm cách tăng tốc độ thay đổi trang và gửi biểu mẫu cũng như chia các trang phức tạp thành các thành phần mà không cần viết bất kỳ mã JavaScript nào, bài đăng này sẽ giúp bạn đưa Rails lên cấp độ tiếp theo với Hotwire. Bài viết này sẽ hướng dẫn bạn cách sử dụng một công cụ để kết xuất phía máy chủ.
Hotwire là gì?
Hotwire cung cấp một cách để xây dựng các ứng dụng web hiện đại mà không cần viết JavaScript bằng cách gửi HTML thay vì JSON qua dây, giúp các trang tải nhanh hơn. Nó duy trì kết xuất ở phía máy chủ và cho phép trải nghiệm phát triển đơn giản hơn và hiệu quả hơn, vì Rails luôn kết hợp vào các công nghệ của nó mà không làm giảm tốc độ hoặc khả năng phản hồi liên quan đến ứng dụng một trang truyền thống (SPA).
Cốt lõi của Hotwire là đá quý 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 và gửi biểu mẫu, chia các trang phức tạp thành các thành phần và truyền tải các cập nhật từng phần của các trang thông qua WebSocket (bao gồm ActionCable, các kênh và dữ liệu trực tuyến).
Tại sao bạn nên sử dụng nó?
Nếu bạn gặp khó khăn với JavaScript và muốn tận dụng trải nghiệm người dùng tốt hơn thông qua cảm giác điều hướng giữa các trang nhanh hơn nhiều, Hotwire là một lựa chọn thay thế cho bạn.
Hotwire hoạt động như thế nào? Hotwire sử dụng kết xuất phía máy chủ (SSR) để giải quyết một số vấn đề liên quan đến các SPA trong khi vẫn duy trì các ưu điểm chính của chúng. SSR đảo ngược quá trình kết xuất, đưa một phần của nỗ lực kết xuất SPA đến máy chủ, tương tự như tải truyền thống. SSR có thể cung cấp cho người dùng khả năng tải ứng dụng hiệu quả hơn vì một số kết xuất được thực hiện trên máy chủ. Ngoài khả năng cải thiện hiệu suất, nó giúp giải quyết một số vấn đề về SEO, chẳng hạn như lập chỉ mục.
Sử dụng có đơn giản không?
Nó rất đơn giản để sử dụng; bạn chỉ cần gói mặc định của một dự án Rails (Ruby, RoR, ActionCable và WebSocket), một viên ngọc Turbo tải xuống tất cả các phụ thuộc JS và Redis để lưu trữ một số dữ liệu tạm thời trong khi duyệt WebSocket.
Bạn không cần phải học một ngôn ngữ khác (JS) để có tốc độ của một ứng dụng web một trang vì Turbo được bổ sung bởi Turbo Drive, Frames, Streams và Native. Thúc đẩy các liên kết và biểu mẫu tăng tốc và giảm nhu cầu tải lại mạng, trong khi Khung phân chia mạng thành các ngữ cảnh độc lập dễ tải hơn.
Nó được sử dụng như thế nào với Rails?
Phần này sẽ hiển thị cho bạn một ví dụ từng bước.
Đối với ví dụ này, chúng tôi sẽ cần:
- Ruby
- Ruby on Rails
- Redis
- SQLite (cơ sở dữ liệu mặc định)
- Gem Hotwire
- TurboRails
- Kích thíchJS
- WebSocket
- ActionCable
Chúng tôi sẽ tạo dự án nào?
Chúng tôi sẽ tạo một dự án truyền thông xã hội.
Đầu tiên, hãy mở thiết bị đầu cuối của bạn. Hãy bắt đầu với một dự án đường ray mới:
rails new social-media
Nhập dự án của bạn:
cd social-media
Thêm Hotwire
Thêm đá quý Hotwire vào dự án của bạn:
bundle add hotwire-rails
Ngoài ra, hãy mở Gemfile
của bạn và thêm cái này:
gem "hotwire-rails"
Nếu bạn sử dụng tùy chọn thứ hai, bạn sẽ cần chạy gói ngay bây giờ.
bundle install
Sau đó, bạn sẽ cài đặt nó.
rails hotwire:install
Cài đặt ban đầu
Bây giờ là thời điểm tuyệt vời để phân tích các cài đặt ban đầu mà Hotwire đã thực hiện. Khi truy cập Gemfile, nó sẽ giống như sau:
gem 'redis', '~> 4.0'
Tại sao chúng tôi cần Redis?
Đá quý Redis đã được thêm vào vì ActionCable cần nó để lưu trữ một số dữ liệu tạm thời trong khi duyệt WebSocket. Tuy nhiên, chỉ cài đặt Redis là không đủ để sử dụng nó. Chúng ta cần kiểm tra xem nó có được cấu hình đúng hay không. Khi bạn truy cập config/cable.yml
tệp, nó sẽ giống như sau:
development:
adapter: redis
redis://localhost:6379/1
Đảm bảo Redis đang chạy khi bạn khởi động ứng dụng của mình (redis-server
).
Phần phụ thuộc JS
Kiểm tra các phần phụ thuộc trên 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
}
Tạo mô hình của chúng tôi
Sau khi kiểm tra tất cả các tệp, chúng tôi sẽ tạo views
của chúng tôi , controllers
, models
và migrations
cho posts
bảng với body
và likes
cột. Để thực hiện việc này, hãy chạy phần sau trong terminal:
rails g scaffold posts body:text likes:integer
Tạo cơ sở dữ liệu của chúng tôi
Bây giờ chúng tôi đã tạo mọi thứ, chúng tôi cần gửi những thay đổi này đến cơ sở dữ liệu, vì vậy hãy chạy như sau trong terminal:
rails db:create db:migrate
Nếu mọi thứ suôn sẻ, chúng tôi có thể chạy máy chủ (rails server
) và kiểm tra xem mọi thứ có ổn không. Để làm như vậy, chúng tôi sẽ chạy máy chủ và sau đó truy cập posts
trang, sẽ là https://localhost:3000/posts
:
màn hình in của thư mục bài đăng
Liệt kê các bài đăng
Bây giờ, chúng tôi sẽ liệt kê các bài viết. Để làm như vậy, chúng tôi sẽ tạo app/views/posts/_post.html.erb
và thêm mã sau vào đó:
<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>
Xác thực
Chúng tôi cần xác thực trường nội dung (không được rỗng) và chúng tôi sẽ yêu cầu chương trình phát sóng hiển thị một tweet trên cùng màn hình với tweet đầu tiên sau khi tạo nó. Để thực hiện việc này, chúng tôi sẽ chỉnh sửa tệp app/models/post.rb
và chèn mã sau:
class Post < ApplicationRecord
validates_presence_of :body
after_create_commit { broadcast_prepend_to :posts }
end
Đặt hàng
Chúng tôi phải sắp xếp các bài đăng của mình, vì vậy hãy mở bộ điều khiển của bạn (app/controllers/posts_controller.rb
).
...
def index
@posts = Post.all.order(created_at: :desc)
@post = Post.new
end
...
Kết thúc
Bây giờ, hãy chỉnh sửa index
của chúng tôi (app/views/posts/index.html.erb
) để hiển thị new post
trang và danh sách tất cả 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 %>
Chuyển hướng đến chỉ mục
Cuối cùng, hãy sửa đổi create
trong bộ điều khiển của chúng tôi. Để tránh chuyển hướng chúng tôi đến show post
, hãy giữ mọi thứ trên cùng một trang.
...
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
...
Trang cuối cùng của chúng tôi sẽ trông như thế này:
màn hình in của trang cuối cùng
Kiểm tra nhật ký
Khi một bài viết được tạo, hãy kiểm tra nhật ký thiết bị đầu cuối của bạn; chúng sẽ trông như thế này:
[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>"
Suy nghĩ
Có nghĩa là ActionCable đang hoạt động với luồng turbo với hiệu suất siêu nhanh, như bạn có thể thấy:Completed 302 Found in 18ms
.
Triển khai
Chúng tôi có cần một tệp thực thi khác để chạy cùng với máy chủ Rails của chúng tôi không?
Không, vì ActionCable hoạt động tốt với các máy chủ phổ biến, chẳng hạn như Unicorn, Puma và Passenger.
Heroku có hỗ trợ Hotwire không?
Có, Heroku hỗ trợ cơ sở của Hotwire (websockets). Nếu bạn có bất kỳ câu hỏi nào khác, bạn có thể xem tài liệu chính thức của Heroku.
Trong trường hợp bạn đang thắc mắc tại sao chúng tôi sử dụng Redis, còn một lý do nữa
Nếu Heroku được sử dụng mà không có Redis, tin nhắn sẽ không được gửi đến mọi người khi ứng dụng của bạn được mở rộng thành nhiều hơn một dyno duy nhất. đến dyno thứ hai. Redis giải quyết vấn đề này bằng cách lưu trữ trạng thái thông báo trong bộ nhớ chung.
Thiết lập Redis trên Heroku
Để thiết lập phiên CLI của Redis với phiên bản Redis từ xa của bạn, hãy sử dụng heroku redis:cli
. Nếu bạn không chỉ định một bản sao, thì bản sao đó nằm tại REDIS_URL
được sử dụng theo mặc định. Nếu bạn có nhiều phiên bản, hãy chỉ định phiên bản mà bạn muốn kết nối.
Nó hoạt động như thế nào trên máy chủ ứng dụng?
Chúng ta cần thiết lập từng dyno để sử dụng hệ thống pub-sub của Redis, tất cả dyno sẽ đăng ký vào cùng một kênh (mặc định) và đợi tin nhắn. Khi mỗi máy chủ nhận được tin nhắn, nó có thể xuất bản nó tới các máy khách được kết nối. Chúng tôi sẽ bao gồm subscribe
trong một chuỗi riêng biệt, với tư cách là subscribe
là một chức năng chặn, do đó, việc chờ đợi một thông báo sẽ dừng quá trình thực thi. Ngoài ra, kết nối Redis thứ hai là cần thiết vì sau khi lệnh đăng ký được thực hiện trên một kết nối, kết nối chỉ có thể hủy đăng ký hoặc nhận tin nhắn. Tìm hiểu thêm về mở rộng quy mô tại đây.
Bảo mật
Hiện tại, ứng dụng đang bị lộ và dễ bị tấn công. Vui lòng thiết lập WSS và khử trùng đầu vào của bạn. Tìm hiểu thêm về Bảo mật WebSocket tại đây.
Kết luận
Có thể sử dụng Hotwire thông qua một ứng dụng mới, như chúng tôi đã trình bày ở đây, nhưng có thể cập nhật từ Turbolinks.
Bài viết này hẳn đã giúp bạn hiểu cách hoạt động của “khung phép thuật”. Trong thực tế, bạn có khả năng phát triển một ứng dụng đơn giản nhỏ hiển thị các yêu cầu thông qua luồng turbo tổng hợp với thao tác và điều hướng qua WebSocket.