了解 hotwired 之前我们想要了解一下现在我们最常用的范式,也就是 SPA - 单页应用。
SPA 的优缺点
单页应用将路由的全部控制到了前端手里,带来更好的交互体验。工作模式分离的很良好,减少了白屏和加载时间。还显著减少了后端服务器的压力。
当然它也带来了很多问题,比如很慢的首屏加载 和 很差的 SEO,当然对于中后台来说这不算什么问题,但是对于 官网 类似的 C 端应用影响就比较大了。
单页应用的解决方案
为了解决以上的问题,前端想到了很多的方案。比较典型的的就是 SSR 家族。
SSR 家族
SSR 是一个比较好的解决方案,如果你想要用单页应用来满足 SEO ,几乎是唯一的方案。
现在 antchain 的官网也是通过 Chair 来实现了 SSR,但是其实做的不是很完美。
这种方式只是能在搜索引擎里面展示准确的搜索词。
百度效果就不是很好。
其实这个技术在国内更多的还是为了解决加载体验问题, 在国内 因为移动互联网的强大,SEO 其实越来越不重要,百度也有点摆烂。
上面的讲述可以看到,SSR 会在服务端计算需要渲染的页面,所以加载时间会有一点延长,为此诞生了很多流派,比较常用的是 NSR 和 ESR。与 SSR 的区别就是HTML在哪里生产。
NSR(Native Side Rendering)首先在 Native 中加载离线页面模板,通过 Ajax 预加载页面数据,通过 Native 渲染生成 HTML 数据并且缓存在客户端。
ESR (Edge Side Rendering):借助边缘计算的能力,将静态内容与动态内容以流式的方式,先后返回给用户。cdn 节点相比于 server,距离用户更近,有着更短的网络延时。
React Server Components
以上的方案其实都在解决首屏渲染的问题,但是用户还是要加载所有的 js,如果有页面用了 moment 还是需要将 moment 引入项目中去,对于用户来说的开销还是很大。而且后续也还是需要加载不小的 JavaScript。
我们加载那么多 js 其实是为了让 JavaScript 通过 json 来生成 生成 React 的 DOM 树,然后让 ReactDom 渲染到页面,那我们能不能一步到位呢?我们直接
这时候我们就想到 Server Components 这个功能
我们直接从服务器获取 React 的组件信息,然后直接渲染出来,我们不需要任何计算,即使使用了 moment ,我们也需要让用户安装,只要 服务端装一份然后直接输出最后的结果。
这样听起来已经很完美了,有交互我们写在前端,没有交互的放在服务端,简直完美,但是我们还是需要安装 React Dom,并且需要 js 生成 html 这个步骤。他也只是号称 Zero-Bundle-Size ,size 最小都需要的 140k(gzip 14k)。
Hotwire
这时候终于到了我们这次需要了解的 Hotwire ,既然我们大部分的开销都是用 js 来生成 html,那我们直接生成 html 不就好了,为啥要传 json,然后 json 生成 html。
Turbo 把几种技术集成到一起以创建快速的、现代的、渐进式增强的 Web 应用而毋需使用太多的 JavaScript。
传统单页面应用的关键吸引力,比较于老式、单独页面的方案而言,就是导航跳转的速度。SPA 是通过仅在第一个页面初始化而非不断地中断应用程序进程从而获得如此高的响应速度的。
大多数 Web 应用程序显示的页面都包含几个独立的片段。对一个讨论区页面,你可能有一个导航栏在顶部,一个消息列表在中间,一个表单在底部以添加新消息,以及一个包含相关主题的侧边栏。生成这种讨论区页面通常意味着以一种序列化方式生成每个片段,把它们拼接在一起,然后把结果以单个 HTML 的响应发布给浏览器。Github 现在就是这么实现的,这么烂的网速竟然都有这么好的访问速度。
<turbo-frame id="messages" src="/messages">
<p>This message will be replaced by the response from /messages.</p>
</turbo-frame>
这可能听起来很像旧时的 frames,甚至
除了把你的片段转化为独立上下文,Turbo Frames 还为你提供了:
- 高效缓存:在上面的讨论区页面范例中,相关主题的侧边栏当一个新主题呈现时(缓存)就需要过期,但中间的消息列表则不用。所有东西只在一个页面时,一旦任何一个片段过期则整个缓存都会过期。借助 frames,每个片段都被独立缓存,因此你可以获得更少依赖 key 的寿命更长的缓存。
- 并行执行:每个懒式加载的 frame 都由其自己的 HTTP 请求/响应所生成,这意味着它可以被单个进程来处理。这允许并行执行而不用手动管理进程。一个复杂的组合页面需要花费 400 ms 完成端到端渲染,则可以被分解为 frames,初始请求可能只需要 50 ms,而三个懒式加载的 frames 每个都耗费 50 ms。现在整个页面 100 ms 就可加载完成,因为那三个 frames 的50 ms 请求是并发而非序列式的。
- 手机友好:在手机 app 中,你通常不会有大而复杂的组合页面。每个片段都需要专用的屏幕。借助 Turbo Frames 构建的应用,你就已经完成了把复杂页面转换为片段的工作。然后这些片段就可以呈现在原生的表格和屏幕中,无需改动(因为它们都有独立的 URL)。
这是 Rails 世界中的一种概念(起初叫 RJS,然后改名为 SJR),是一种无需任何 JavaScript 的一种实现,优点是非常明显的。
写在最后
- SPA 对首屏时间不是很友好,大大拉低了其优势,尤其是在重视 SEO 的国外。
- SSR,NSR,ESR 各有各的有点,但是还是需要加载很多 js,渲染时间无法节省。
- React Server Components 虽然号称 Zero-Bundle-Size,但是 React 本身也是个不小的 Bundle-Size。
- Hotwire 直接把 html 当成 JSON 使用,是一个单页的多页应用,可以大大的减少 js 的使用,但是其交互性会差一下,在 移动端 和 弱交互领域用起来会更加爽,并且收益足够大。