Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế

Turbolinks, một công cụ tuyệt vời giúp điều hướng ứng dụng web nhanh hơn, không còn được phát triển tích cực. Nó đã được thay thế bởi một framework mới gọi là Turbo, thuộc hệ sinh thái Hotwire.

Đội ngũ phát triển hiểu rằng các khái niệm khác có thể áp dụng các ý tưởng tương tự được trích xuất từ Turbolinks để tuân thủ web nhanh hơn, chẳng hạn như frames, gửi form và ứng dụng native.

Bài viết này nhằm cung cấp hướng dẫn về framework Turbo - sự thay thế mới cho Turbolinks, bao gồm hướng dẫn di chuyển thực tế giải thích cách sử dụng các phần quan trọng và thường dùng nhất của Turbolinks trong Turbo.

Để hiểu tốt hơn nội dung chúng ta sẽ thảo luận, cần có một chút kiến thức về Turbolinks. Bạn có thể đọc thêm tại đây và đây.

Giới thiệu Turbo

Turbo là tập hợp một số kỹ thuật để tạo ứng dụng web hiện đại, nhanh chóng với ít JavaScript hơn. Nó thực hiện điều này bằng cách cho phép máy chủ xử lý tất cả logic sẽ được chuyển dưới dạng HTML trực tiếp đến trình duyệt. Lúc này, trách nhiệm duy nhất của trình duyệt là xử lý HTML thuần túy.

Để làm được điều này, Turbo chia thành bốn phần chính:

  • Turbo Drive, lõi của Turbo, tránh tải lại toàn trang bằng cách tự động chặn tất cả các click vào link và form, ngăn trình duyệt gọi mặc định, thay đổi URL qua History API, yêu cầu trang ngầm qua Ajax và hiển thị phản hồi phù hợp.
  • Turbo Frames xử lý các tập hợp con/trang con của trang bằng cách tái định nghĩa cách các lập trình viên front-end xử lý frames để xử lý độc lập các tập hợp con của trang. Nó phân rã trang thành các tập hợp ngữ cảnh độc lập với phạm vi riêng và khả năng tải lười.
  • Turbo Streams giúp thay thế việc cập nhật trang một phần thông thường qua truyền tải bất đồng bộ qua WebSocket bằng một tập hợp thẻ container CRUD đơn giản. Với chúng, bạn có thể gửi các đoạn HTML qua cùng WebSocket và để trang hiểu và xử lý lại UI.
  • Turbo Native cung cấp tất cả công cụ cần thiết để xử lý Turbo trong ứng dụng web nhúng cho shell native nếu bạn phát triển native trên iOS/Android.

Thiết lập dự án

Để tăng tốc tiến độ, tôi cung cấp sẵn một dự án Rails có form bài viết (posts) được scaffold sẵn, cùng với Bootstrap cho việc styling.

Điều này giúp bạn không mất thời gian thiết lập, đồng thời có một dự án hoạt động với Turbolinks đã được thêm sẵn. Nếu bạn đã có dự án riêng, cũng không sao; bạn vẫn có thể theo dõi bài viết.

Bạn cũng có thể tạo mới một ứng dụng Rails được scaffold bằng lệnh rails.

Bạn có thể tìm link GitHub của repository tại đây. Hãy clone về máy và chạy lệnh bundle install để cài đặt tất cả dependencies của Rails.

Sau khi mọi thứ sẵn sàng, khởi động server Rails qua lệnh rails s và truy cập URI /posts, như hình dưới:

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế CRUD Posts trong Rails

Để kiểm tra tính năng Turbolinks hoạt động, chỉ cần điều hướng qua các link tạo bài viết mới hoặc hiển thị chi tiết. Bạn sẽ thấy URL thay đổi mà không tải lại trang.

Các bước di chuyển

Bắt đầu với cài đặt package Node. Vì không còn cần turbolinks, chúng ta có thể gỡ bỏ nó khỏi danh sách Node và thêm dependency turbo-rails, như hai lệnh dưới:

yarn remove turbolinks
yarn add @hotwired/turbo-rails

Một cách tuyệt vời khác để đảm bảo mọi thứ cài đặt đúng, nếu bạn làm việc với Rails, là chạy lệnh sau:

rails turbo:install

Lệnh này sẽ cài Turbo qua npm nếu Webpacker đã được cài trong ứng dụng (đúng vậy). Lệnh này cũng cố gắng gỡ bỏ tất cả dependencies cũ của Turbolinks khỏi dự án nếu bạn bỏ sót điều gì.

Sau đó, mở file app/javascript/packs/application.js và tìm các dòng code sau:

import Turbolinks from "turbolinks";
Turbolinks.start();

Lưu ý rằng các import có thể thay đổi nhẹ tùy phiên bản Rails app (phiên bản cũ dùng require thay vì import). Tuy nhiên quy trình giống nhau cho cả hai.

Thay thế chúng bằng dòng sau:

import "@hotwired/turbo-rails";

Chỉ cần một import duy nhất; không cần khởi động thủ công. Instance Turbo được gán tự động vào object window.Turbo khi import, dễ quản lý hơn.

Để kiểm tra xem chúng ta đã chỉ dùng Turbo chứ không còn Turbolinks, hãy thêm đoạn code sau vào cuối file:

$(document).on("turbolinks:load", () => { console.log("turbolinks!"); });
$(document).on("turbo:load", () => { console.log("turbo!"); });

Sau khi reload trang trong trình duyệt, kiểm tra console log để xem gì được in ra:

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế Kiểm tra log sự kiện load Turbo

Còn một thay đổi cần làm ở file app/views/layouts/application.html.erb, cụ thể là đổi các data attribute cũ của Turbolinks sang Turbo tương đương. Tìm hai thẻ dùng attribute data-turbolinks-* và thay bằng:

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbo-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbo-track': 'reload' %>

Điều này quan trọng để Turbo tự động theo dõi tất cả asset được import trong thẻ head và reload chúng nếu có thay đổi. Áp dụng cho mọi file, bao gồm scripts và styles bạn thêm ở đó.

Khám phá các tính năng Turbo

Vì Turbo tự động chặn tất cả link trong ứng dụng để gọi mà không reload, nếu bạn cần tắt chức năng đó cho một link cụ thể, ví dụ, bạn phải code tường minh.

Hãy test bằng cách cập nhật nút "New Post" trong file app/views/posts/index.html.erb như sau:

<%= link_to 'New Post', new_post_path, :class => "btn btn-primary btn-sm", "data-turbo" => "false" %>

Lưu ý chúng ta thêm rõ ràng attribute data-turbo mới, yêu cầu Turbo không xử lý link này khi click.

Nếu reload ứng dụng và click nút "New Post", bạn sẽ thấy trang tải lại hoàn toàn như ứng dụng thông thường.

Đây cũng là cách tuyệt vời để test xem Turbo đã được cài đặt và hoạt động trong ứng dụng chưa.

Tương tự cho form. Turbo tự động xử lý mọi submit form bất đồng bộ. Nếu muốn tắt cho form dưới app/views/posts/_form.html.erb, hãy đổi nút submit thành:

<div class="actions">
<%= form.submit class: "btn btn-primary btn-sm", "data-turbo" => false %>
</div>

Reload app và test! Bạn sẽ thấy hành vi tương tự khi tạo bài viết mới.

Gửi Form

Nói về form, Turbo xử lý chúng rất giống như link. Tuy nhiên, request form không luôn kết thúc thành công.

Hãy xem thực tế! Trước tiên, thêm vài validation để thuộc tính name và title của post trở thành bắt buộc. Mở file app/models/post.rb và sửa thành:

class Post < ApplicationRecord
  validates :name, presence: true
  validates :title, presence: true
end

Reload app và thử thêm bài viết mới, để trống mọi trường. Bạn sẽ thấy không có gì xảy ra. Nếu kiểm tra console trình duyệt, bạn sẽ thấy tương tự như sau:

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế Phản hồi form phải redirect đến vị trí khác

Để sửa, có hai cách. Cách đầu: thêm status vào các action có thể update của post controller (POST, PUT, v.v.) và cho nó nhận object unprocessable entity làm giá trị.

Dưới đây là thay đổi code cho cả hai method create và update (post_controller.rb):

# def create
format.html { render :new, status: :unprocessable_entity }
# def update
format.html { render :edit, status: :unprocessable_entity }

Lưu chỉnh sửa và test form lại. Bạn sẽ thấy lỗi validation hiển thị đúng:

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế Hiển thị lỗi validation trên UI

Cách thứ hai là qua turbo_frame_tag. Trong Rails app dùng Turbo, Turbo Frames được render bằng tag này.

Đây là tài nguyên tuyệt vời khi bạn muốn tách một phần trang và mở đường hầm trực tiếp với backend app để Turbo gắn request và response vào frame cụ thể đó.

Để test, trước tiên bọc toàn bộ nội dung file _form.html.erb trong tag này:

<%= turbo_frame_tag post do %>
...
<% end %>

Tham số post ở đây rõ ràng trong trường hợp form. Khi quay lại trình duyệt và test lại, cùng lỗi validation sẽ hiện như mong đợi.

Một điều thú vị khác là HTML được sinh ra cho form đó. Hãy xem:

<turbo-frame id="new_post">
<form action="/posts" accept-charset="UTF-8" method="post">
...
</form>
</turbo-frame>

Element HTML tùy chỉnh này là cách Turbo phân biệt frames với các action dựa trên toàn trang.

Thanh tiến trình

Lý do phổ biến là khi bạn bỏ cơ chế tải mặc định của trình duyệt, bạn nên cung cấp cái khác cho trường hợp trang tải chậm.

Turbo đã cung cấp sẵn thanh tiến trình dựa trên CSS ở đầu trang, rất giống với các thư viện lớn như Bootstrap và Material Design.

Nó được thiết lập hiển thị chỉ khi request mất hơn 500 ms để xử lý, chưa đủ lâu cho dự án test của chúng ta.

Nếu bạn muốn thay đổi style hoặc thậm chí xóa hoàn toàn, bạn có thể tùy chỉnh class CSS .turbo-progress-bar, như sau:

.turbo-progress-bar {
  height: 15px;
  background-color: gold;
}

Để test, bạn cần giảm độ trễ thanh tiến trình trong file application.js với code sau:

window.Turbo.setProgressBarDelay(1);

Thời gian cung cấp tính bằng mili-giây. Dưới đây là biểu diễn style cập nhật cho thanh tiến trình.

Chuyển từ Turbolinks sang Turbo: Hướng dẫn Di chuyển Thực tế Hiển thị thanh tiến trình cập nhật

Kết luận

Còn nhiều thứ để thảo luận về Turbo và các tính năng tuyệt vời của nó, như module Streams và Native. Tuy nhiên, để bài viết tập trung, chúng ta dừng ở các bước ban đầu.

Như thường lệ, tôi không thể không khuyên đọc Turbo Handbook chính thức, rất hữu ích khi tôi bắt đầu quá trình di chuyển này. Tại đó, bạn sẽ tìm thấy tất cả tài liệu cần thiết để xử lý các điều kiện đặc biệt của dự án.

Nếu app của bạn dùng Devise, ví dụ, rất có thể bạn cần một số điều chỉnh. May mắn là team Turbo đã cung cấp tutorial tuyệt vời về chủ đề này để giúp giải quyết các chi tiết nhỏ quanh Devise với Turbo.