Rails6 Turbo详解

永恒的Web开发目标

  • 更快的加载速度
  • 更好的可维护性

前后端分离带来的问题

  • JSON API 调试成本
  • 重复数据传递
  • 大量无必要的重复轮子
    • 重复路由
    • 重复校验
  • 高昂的学习成本(调试成本)
  • 新问题
    • SSR问题

我的全栈经历

  • 2012年正式使用 Rails3.x + jQuery + Coffee
  • 2014年使用 Rails4.1.9 + Angular1.4
  • 2016-2018年使用 Rails5 + React
  • 2020年至今, showmebug 采用 Rails6 全家桶外加 VueJS

Rails UJS+SJR 的问题

  • Dry-Quick
  • 模块化不够
  • 代码不健壮
  • 跟现有前端社区有冲突

Rails6.1 全新架构

  • Webpacker
  • Turbo
    • Drive
    • Frame
    • Stream
  • Stimulus

全栈工程师必备杀手级架构

  • 比单页应用还好的用户体验
  • 模块化页面设计
  • 无任何重复(无须前端路由、数据、校验)

今天我们重点讲讲Turbo Drive

Turbo 是 “Turbolinks6”

Turbo

  • 用 TypeScript 重写( 之前是 Coffee )
  • Turbolinks5 的基础上增加了 Form 监听
  • 增加了 Turbo Frame 和 Turbo Stream

未使用Turbo

使用Turbo后

Turbo 的核心原理

每个页面 HEAD 几乎不变,通过监听 Link 和 Form 的点击,只处理Body内容替换,进而降低页面渲染最高的成本:JS和CSS的解析。

yarn remove turbolinks
yarn add @hotwired/turbo

Turbo 的安装

import Turbo from "@hotwired/turbo"

然后将代码中所有的 Turbolinks 替换为 Turbo

$(document).on('turbo:load', function(){
  // your code here
  // 等同于 ready 事件
})

Turbo 的平常使用

$(document).on('turbo:before-render', function(){
  
  // your code here
  // 一些 unload 相关的代码

})

使用上的一些注意事项

  • 保持幂等
  • 第三方SDK(如微信)
  • 特定页面关闭 turbo

幂等是导致放弃 Turbo 的根本原因

$(document).on('turbo:load', function(){
  $(body).append("123");
})

解决幂等问题

$(document).on('turbo:load', function(){
  $(body).append("123");
})

$(document).on('turbo:before-render', function(){
  // undo this action
})
<meta name="turbo-cache-control" content="no-cache">

方案一

方案二(推荐,关掉cache,体验更真实)

解决幂等问题

import { Controller } from "stimulus"
import 'select2'

export default class extends Controller {
  static targets = [ 'label' ]

  connect() {
    $(this.labelTarget).select2({
    })
  }

  disconnect() {
    $(this.labelTarget).select2('destroy')
  }
}

方案三

临时关闭页面 turbo

<meta name="turbo-visit-control" content="reload">
<a href='' data-turbo='false'>

Turbo 原理图

Turbo-Frame

将前端复杂逻辑交还 Rails MVC 优雅处理

Turbo-Stream

用 Rails 控制前端 CRUD

示例交给下一个同学分享

其他补充

超级复杂的页面可以使用 ReactComponent 或 VueJS 

总结

  • Turbo + Frame + Stream + Stimulus
  • 全栈解决之道
  • 至少提高100%以上的效率