Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง

Turbolinks เป็นเครื่องมือที่ช่วยให้การนำทางในเว็บแอปพลิเคชันเร็วขึ้น แต่ปัจจุบันไม่ได้รับการพัฒนาต่อแล้ว มันถูกแทนที่ด้วยเฟรมเวิร์กใหม่ชื่อ Turbo ซึ่งเป็นส่วนหนึ่งของชุดเครื่องมือ Hotwire

ทีมพัฒนาเข้าใจว่ามีหลายสิ่งที่สามารถนำแนวคิดจาก Turbolinks ไปใช้ได้ เพื่อสร้างเว็บที่เร็วขึ้น เช่น frames, การส่งฟอร์ม และแอปพลิเคชันเนทีฟ

บทความนี้มีเป้าหมายเพื่อให้คู่มือสำหรับเฟรมเวิร์ก Turbo ซึ่งเป็นตัวแทนที่ใหม่ของ Turbolinks รวมถึงคู่มือการย้ายแบบปฏิบัติจริงที่จะอธิบายวิธีใช้งานส่วนที่สำคัญและนิยมใช้มากที่สุดของ Turbolinks ใน Turbo

เพื่อให้เข้าใจเนื้อหาได้ดีขึ้น ควรมีความรู้พื้นฐานเกี่ยวกับ Turbolinks สามารถอ่านเพิ่มเติมได้ที่ ที่นี่ และ ที่นี่

รู้จัก Turbo

Turbo เป็นชุดของเทคนิคหลายอย่างสำหรับสร้างเว็บแอปพลิเคชันสมัยใหม่และรวดเร็วด้วย JavaScript น้อยที่สุด ทำได้โดยการให้เซิร์ฟเวอร์จัดการตรรกะทั้งหมดที่จะส่งมอบในรูปแบบ HTML โดยตรงไปยังเบราว์เซอร์ ส่วนเบราว์เซอร์มีหน้าที่เพียงประมวลผล HTML ธรรมดาเท่านั้น

เพื่อทำเช่นนี้ Turbo แบ่งตัวออกเป็น 4 ส่วนหลัก:

  • Turbo Drive หัวใจของ Turbo ป้องกันการโหลดหน้าใหม่ทั้งหน้าผ่านการกดคลิกที่ลิงก์และฟอร์มทั้งหมดโดยอัตโนมัติ ป้องกันเบราว์เซอร์จากการเรียกใช้ เปลี่ยน URL ผ่าน History API ขอหน้าต่อไปผ่าน Ajax และแสดงผลการตอบกลับอย่างเหมาะสม
  • Turbo Frames จัดการกับส่วนย่อยของหน้า/เฟรม โดยนำเสนอวิธีใหม่ที่นักพัฒนาฟรอนต์เอนด์จัดการกับเฟรมเพื่อดูแลส่วนย่อยของหน้าแยกกัน แบ่งหน้าออกเป็นชุดบริบทอิสระที่มีขอบเขตและความสามารถในการโหลดแบบ Lazy load แยกจากกัน
  • Turbo Streams ช่วยแทนที่การอัปเดตหน้าบางส่วนทั่วไปผ่านการส่งมอบแบบ Async ผ่าน WebSocket ด้วยชุดแท็กคอนเทนเนอร์ CRUD ที่เรียบง่าย ด้วยเหตุนี้ คุณสามารถส่งชิ้นส่วน HTML ผ่าน WebSocket เดียวกันและให้หน้าเข้าใจและประมวลผล UI ใหม่ได้
  • Turbo Native 提供工具来在iOS/Android原生外壳中处理嵌入式Web应用中的Turbo

การตั้งค่าโปรเจกต์

เพื่อให้ดำเนินการรวดเร็วขึ้น ผมได้เตรียมแอป Rails พร้อมใช้งานที่มี scaffold สำหรับฟอร์มโพสต์พร้อม Bootstrap สำหรับการจัดสไตล์

สิ่งนี้จะช่วยประหยัดเวลาในการตั้งค่า และให้โปรเจกต์ที่ทำงานได้พร้อมกับ Turbolinks ที่ติดตั้งไว้แล้ว หากคุณมีโปรเจกต์ของตัวเองอยู่แล้ว ก็ไม่เป็นไร คุณยังคงสามารถทำตามบทความได้

คุณยังสามารถสร้างแอป Rails ใหม่พร้อม scaffold ด้วยคำสั่ง rails ได้เช่นกัน

ลิงก์ GitHub ของ repository อยู่ ที่นี่ โปรด clone มาในเครื่องและรันคำสั่ง bundle install เพื่อติดตั้ง dependencies ของ Rails ทั้งหมด

เมื่อตั้งค่าเสร็จแล้ว ให้เริ่มเซิร์ฟเวอร์ Rails ด้วยคำสั่ง rails s และตรวจสอบ URI /posts ตามภาพด้านล่าง:

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง Posts CRUD ใน Rails

เพื่อทดสอบฟีเจอร์ของ Turbolinks ให้ลองนำทางผ่านลิงก์สร้างโพสต์ใหม่หรือแสดงรายการ คุณจะเห็น URL เปลี่ยนโดยไม่มีการโหลดหน้าใหม่

ขั้นตอนการย้าย

เริ่มจากการติดตั้ง Node package เนื่องจากไม่ต้องการ turbolinks แล้ว เราสามารถลบออกจากรายการ Node และเพิ่ม dependency turbo-rails ดังคำสั่งด้านล่าง:

yarn remove turbolinks
yarn add @hotwired/turbo-rails

วิธีอีกอย่างที่ดีสำหรับ Rails คือการรันคำสั่ง:

rails turbo:install

คำสั่งนี้จะติดตั้ง Turbo ผ่าน npm หาก Webpacker ติดตั้งอยู่ในแอปพลิเคชัน ซึ่งเป็นจริง คำสั่งนี้ยังพยายามลบ dependencies เก่าของ Turbolinks ออกจากโปรเจกต์ในกรณีที่คุณพลาด

จากนั้นเปิดไฟล์ app/javascript/packs/application.js และค้นหาบรรทัดต่อไปนี้:

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

หมายเหตุ: การ import อาจแตกต่างกันเล็กน้อยขึ้นอยู่กับเวอร์ชัน Rails (เวอร์ชันเก่าใช้ require แทน import) แต่กระบวนการเหมือนกัน

แทนที่ด้วยโค้ดต่อไปนี้:

import "@hotwired/turbo-rails";

เพียง import เดียว ไม่ต้อง start ด้วยตนเอง เนื่องจาก instance Turbo จะถูกกำหนดให้ window.Turbo อัตโนมัติเมื่อ import ซึ่งจัดการง่ายกว่า

เพื่อทดสอบว่าเราใช้ Turbo ไม่ใช่ Turbolinks แล้ว ให้เพิ่มโค้ดต่อไปนี้ท้ายไฟล์:

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

หลังโหลดหน้าใหม่ในเบราว์เซอร์ ตรวจสอบ console logs จะเห็นว่า:

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง ตรวจสอบ Turbo load event log

มีการเปลี่ยนแปลงอีกอย่างในไฟล์ app/views/layouts/application.html.erb คือการเปลี่ยน data attributes เก่าของ Turrolinks เป็นของ Turbo ค้นหาแท็ก 2 ตัวที่ใช้ data-turbolinks-* และแทนที่ด้วย:

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

สิ่งนี้สำคัญเพื่อให้ Turbo ติดตาม assets ที่ import ในแท็ก head อัตโนมัติ และโหลดใหม่หากมีการเปลี่ยนแปลง ใช้ได้กับทุกไฟล์ รวมถึง scripts และ styles ที่เพิ่มไว้

สำรวจฟีเจอร์ของ Turbo

เนื่องจาก Turboกดคลิกลิงก์ทั้งหมดในแอปพลิเคชันเพื่อเรียกใช้โดยไม่โหลดใหม่ หากต้องการปิดฟังก์ชันนี้สำหรับลิงก์เฉพาะ ต้องเขียนโค้ดระบุชัดเจน

ลองทดสอบโดยอัปเดตปุ่ม "New Post" ใน app/views/posts/index.html.erb เป็น:

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

เราเพิ่ม attribute data-turbo เพื่อขอ Turbo ไม่จัดการลิงก์นี้เมื่อคลิก

โหลดแอปพลิเคชันใหม่และคลิกปุ่ม "New Post" จะเห็นหน้าโหลดเต็มที่เหมือนแอปทั่วไป

นี่เป็นวิธีทดสอบที่ดีว่า Turbo ตั้งค่าและทำงานแล้ว

ฟอร์มก็เช่นกัน Turbo จัดการการส่งฟอร์มทั้งหมดแบบ asynchronous หากต้องการปิดสำหรับฟอร์มใน app/views/posts/_form.html.erb ให้เปลี่ยนปุ่มส่งเป็น:

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

โหลดแอปและทดสอบ จะเห็นพฤติกรรมเดียวกันเมื่อสร้างโพสต์ใหม่

การส่งฟอร์ม

เกี่ยวกับฟอร์ม Turbo จัดการคล้ายกับลิงก์ แต่คำขอฟอร์มไม่เสมอไปสำเร็จ

ลองดูในทางปฏิบัติ! ก่อนเพิ่ม validation ให้ name และ title ของโพสต์เป็น required โดยเปิด app/models/post.rb และแก้เป็น:

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

โหลดแอปและลองเพิ่มโพสต์ใหม่โดยเว้นช่องว่าง คุณจะสังเกตว่าไม่มีอะไรเกิดขึ้น หากตรวจสอบ browser console จะเห็นข้อความ:

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง Form responses ต้อง redirect ไปยังตำแหน่งอื่น

มี 2 วิธีแก้ไข วิธีแรกคือเพิ่ม status ให้แต่ละ action ที่อัปเดตได้ของ post controller (POST, PUT, ฯลฯ) และให้รับค่า unprocessable entity

โค้ดเปลี่ยนแปลงสำหรับเมธอด create และ update (post_controller.rb):

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

บันทึกและทดสอบฟอร์มอีกครั้ง จะเห็นข้อผิดพลาดแสดงถูกต้อง:

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง แสดงข้อผิดพลาด validation ใน UI

วิธีที่สองคือใช้ turbo_frame_tag ใน Rails app ที่ใช้ Turbo Turbo Frames ที่กล่าวมา จะถูก render โดยแท็กนี้

เป็นทรัพยากรที่ดีเมื่อต้องการแยกส่วนของหน้าและเปิดการเชื่อมต่อโดยตรงกับ backend เพื่อให้ Turbo ผูกคำขอและตอบกลับกับเฟรมเฉพาะนั้น

ทดสอบโดย wrap เนื้อหาทั้งหมดของ _form.html.erb ด้วยแท็กนี้:

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

post อยู่ที่นั่นเพื่อเหตุผลที่ชัดเจนในกรณีฟอร์ม กลับไปทดสอบในเบราว์เซอร์ validation errors จะแสดงเหมือนเดิม

สังเกต HTML ที่สร้างขึ้นสำหรับฟอร์มนั้น:

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

custom HTML element นี้คือวิธีที่ Turbo แยก frames จาก whole-page actions

แถบความคืบหน้า

เป็นสัญชาตญาณที่เมื่อเอา mechanism โหลดเริ่มต้นของเบราว์เซอร์ออก คุณควรให้ mechanism ใหม่สำหรับกรณีที่หน้าโหลดช้า

Tururo มี progress bar แบบ CSS built-in ที่ด้านบนหน้า คล้ายกับ library ใหญ่ๆ เช่น Bootstrap และ Material Design

มันตั้งค่าแสดงเฉพาะเมื่อ request ใช้เวลานานกว่า 500 ms ซึ่งไม่ค่อยนานพอสำหรับโปรเจกต์ทดสอบ

หากต้องการเปลี่ยนสไตล์หรือลบออก สามารถปรับคลาส CSS .turbo-progress-bar ได้ ดังนี้:

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

ทดสอบโดยลด progress bar delay ใน application.js ด้วยโค้ด:

window.Turbo.setProgressBarDelay(1);

เวลาเป็นมิลลิวินาที ด้านล่างคือการแสดงผล progress bar ที่อัปเดตแล้ว

การย้ายจาก Turbolinks ไป Turbo: คู่มือการย้ายแบบปฏิบัติจริง แสดง progress bar ที่อัปเดตแล้ว

สรุป

ยังมีอะไรมากมายเกี่ยวกับ Turbo และฟีเจอร์สุดโตด เช่น Streams และ Native modules แต่เพื่อให้บทความโฟกัส เราจะหยุดที่ขั้นตอนเริ่มต้นนี้

เหมือนเดิม ผมแนะนำ Turbo Handbook อย่างเป็นทางการ ซึ่งเป็นประโยชน์มากเมื่อเริ่มกระบวนการย้าย คุณจะพบวัสดุทั้งหมดที่ต้องการสำหรับเงื่อนไขพิเศษของโปรเจกต์

หากแอปใช้ Devise ตัวอย่างเช่น อาจต้องปรับเปลี่ยนบางอย่าง ทีม Turbo มี tutorial ดีเยี่ยมเกี่ยวกับเรื่องนี้ช่วยจัดการรายละเอียดรอบ Devise กับ Turbo