Rails 白话文讲 Turbo Drive

lanzhiheng · June 03, 2021 · Last by jicheng1014 replied at June 11, 2021 · 940 hits

这篇文章用白话文来讲解一下 Turbo Drive。作为 Hotwire 工具库中的核心功能,简单的配置就能给交互体验带来很大的提升。原文链接 https://www.lanzhiheng.com/posts/turbo-drive-simple-talking

交互机制

Turbo 由很多个部件做成,我们先从Turbo Drive入手。Drive 中文可翻译为“驱动”或“驾驶”。在这里意味着驱动页面的切换。可以想象一个最简单的交互场景点击页面上的链接,并跳转,Turbo 的官方文档是这样说的

This happens by intercepting all clicks on links to the same domain. When you click an eligible link, Turbo Drive prevents the browser from following it, changes the browser’s URL using the History API, requests the new page using fetch, and then renders the HTML response.

简单总结一下,它先做了下面这些事情

  1. 拦截掉浏览器原生的点击事件(原来的点击事件会导致全页面刷新)。
  2. 对目标页面的 URL 发送 GET 请求,获取整个页面数据。
  3. 通过 HistoryAPI 来修改浏览器的路由。

接下来

During rendering, Turbo Drive replaces the current

element outright and merges the contents of the element. The JavaScript window and document objects, and the element, persist from one rendering to the next.

前面提到的第二步会异步获取到新页面数据,这个时候它会合并<head>元素里面的内容,并且替换掉<body>里面的东西。这个过程是通过 Ajax 技术来实现的,所以用户不会感受到全页面重新加载的那种闪烁感,交互体验大幅度提升,页面加载也更迅速。

下面有一些我个人博客页面(已开启 Turbo)的效果图

下面截图的是页面首次加载时所发的请求,这是浏览器常规的获取页面方式,请求类型是Doc,这没什么好说的,就算是单页面应用首次加载也会发这个请求。

first-load.png

接下来我在该站点随机点击一些链接,发现最后Doc分类下依旧还是只有一个请求,其他请求全部到了XHR分类下,这就意味着,除了第一个请求(首次加载)之外,其他都是异步请求。借此 Turbo 为我们提供了更为平滑的页面切换过程。

second-load.png

multi-navigation.png

对比单页面应用

当然了,就请求数据量来讲肯定是比不上单页面应用,因为单页面应用数据交互的过程都是采用了 JSON,请求的数据量相对来说会更少一些。而 Turbo 在默认情况下(先抛开 Frame 不谈)几乎每次页面跳转都需要获取整个页面的数据,有一部分重复数据其实我们是不需要的。

不过 Turbo 依旧有它的优势,配置异常简单。只需要在项目中简单引入 Turbo 的 JS 库,不需要太多的配置(几乎就不用配置),就能大幅度地提升页面的交互体验(异步更新页面与全页面刷新相比,对用户来说体验是完全不同的)。而如果是单页面应用,我们可能一开始会引入 React,Vue 这样的框架,然后一步步用 JS 去构造整个站点,其中还会涉及各种配置语法糖的抉择问题(当然可能还会有撕逼的过程),换个角度想也是一种成本。

总结

就个人体会来说,对于一般的交互不是那么重的页面,我首选Hotwire。而那些 Hotwire 确实难以胜任的工作(说不定以后会胜任),我会考虑单独引入 React/Vue 来解决它们。可能有技术情节的朋友会觉得这点无法忍受,然而,成本确实摆在那里。要是我们也像阿里巴巴那么有钱,个人倒不介意请人把所有页面都用前端框架重写一遍,而是事实,我们没有。

这篇文章简单聊了下Turbo Drive,接下来会谈谈Turbo Frame,了解如何对页面进行更细粒度的控制。

我是在 hotwire 的时候也用了 react_component, 但是在加载 react_component 的时候,会闪一下。不知道有没有哪位大佬解决好了这个问题

Reply to jicheng1014

会不会是跳转的时候 body 里面的元素被 replace 的时候导致的?

Reply to lanzhiheng

我自己的分析哈

就是服务器 render 的时候 react_component 的组件只是个 空 div 他还要等 react renderDOM 这个空 div , 渲染完毕了才有新界面

Reply to jicheng1014

@jicheng1014 你这个闪烁会不会是 preview 导致的? https://turbo.hotwire.dev/handbook/building#opting-out-of-caching

加一下这个标签看看? <meta name="turbo-cache-control" content="no-preview">

Reply to lanzhiheng

不是 是因为 渲染是在 服务器加载完 dom 之后 react 需要运算 继续修改 dom 导致的

You need to Sign in before reply, if you don't have an account, please Sign up first.