Rails Rails 前端 Turbo 的未来的花样:Morphing

jicheng1014 · 2023年10月27日 · 最后由 jisuanjixue 回复于 2023年11月04日 · 1080 次阅读

最近在看 Rails world 2023 的视频,这里谈到了 Turbo 的进一步的未来,有事件的朋友可以看下这个

https://www.youtube.com/watch?v=m97UsXa6HFg

看了之后,我觉得 Rails 的前端继续在邪路上偏离主流一发不可收拾了

另付补充文字

https://dev.37signals.com/a-happier-happy-path-in-turbo-with-morphing/


大致说下视频的内容:

Jorge 总结了下 现有的 Turbo Stream 和 Turbo frame 的问题:兔子洞,到处都是代码片段,还需要对不同的 View 的情况下考虑,这让程序员很不开心。

他认为程序员写页面的时候,最开心的就是 给出请求,之后服务器给出整个返回 就行了。但是这么的话对展现力确实有很大的影响,不会保持浏览器滚动条、其他 dom 节点状态,会有白屏,位置视口变动等问题

那么有没有解决方案,既可以解决程序员写的爽(即只写全部渲染页面),又保留浏览器滚动条、其他 dom 节点状态的方式呢?

答案是有,他参考了其他框架(phoenix 的 Liveview?)采取的 morphing 的技术,即使用浏览器将服务器返回的整个页面的的 dom 树,对比请求之前页面之前的 dom 树,之后将 dom 树的不同的东西更新上就行了。其实这个就比较类似 react 的 虚拟节点更新,只不过这里不是虚拟节点,而是真实的 dom 树,无所谓,现在的浏览器都可以很快很好完成这个工作

利用 morphing 技术,浏览器会找到不同的 dom,更新它,并保持之前的 scrollbar 位置等信息了。大家就可以不写兔子洞,就只管整体渲染一次页面就好了。

视频演示了下在 basecamp 的 类似看板的地方,将滚动条拉到了面板的最右侧,点击添加新的面板,页面的滚动条并未消失,而是直接在原来最右侧的地方又新增了一个,整个效果就如同使用 react 那种感觉一样。然而这种使用 morphing 的技术则不需要重新写任何代码,就用之前的 render 整个页面的那个即可。

之后另外使用 broadcast 也实现了类似的效果,即不需要重新写其他 view,就复用即可


总结下:就是就前端方面 rails 就只写最普通的 view 爽就完了,剩下的靠 morph 来更新页面的同时,保持之前的浏览器状态,获得 One Page Application 的体验,与主流前端那套是 say goodbye 了。

我自己的感觉是浪费的拿点传输大小和 CPU 消耗,对比现在的 网络和计算机性能,真的无所谓了。只不过国内的各路卷王,怕是不会用在生产环境的。

人工比这些 cpu 资源贵多了

既然前端发展出了 serverless,前端控制一切的系统。后端当然也要发展出 clientless,只返回静态的 html,所有逻辑全在后端控制的系统。

前端的方案有成本优势。 通过接口获得差异数据,前端动态生成 diff 组件。充分利用客户端算力。

后端的方案,压力全部自己扛。看钞能力。

回归本质,我觉得挺好的

有了这玩意,Turbo frame 下的 redirect 和 flash 应该能优雅的解决了吧

6 楼 已删除

Turbo 解决了一些问题,同时也带来新的问题。再加上 Stimulus 完全没生态。还是得搭配 React 使用。 前后分离是一个很完美的搭配,Rails 与其硬刚前端,不如搞一个和 React 完美整合的方法。

316786359 回复

最近写微信小程序深有体会,被那一堆的 view 恶心死了,还有那恶心的逻辑判断方式。后来我就在后端完成所有逻辑,前端模板只有个 for 循环。

zhongsheng 回复

无论用什么开发前端,尽量把逻辑处理放在后端完成,前端尽量做到只负责显示数据。这是我做项目一贯的要求或者叫追求。和用什么前端或者平台实现无关。

mfb777 回复

jsbundling 我觉得就是一个解决这种撕裂的不错的方式

我们在讨论 生态的 时候,我觉得可能讨论的是 有没有一个行业型的 模版,比如 类似 element 或者 antdesign 用来避免写重复的组件 这方面确实 rails 差一些

只不过我觉得传统里的由前端接管路由的方式 不是一个好方式

mfb777 回复

前后端分离不是很符合 Rails 极致效率的目标。

我看用到https://github.com/basecamp/idiomorph/tree/rollout-build ,basecamp 采用 idiomorph

morphdom 使用节点的 id 属性来匹配给定的同级节点集中的元素。当找到 id 匹配时,现有元素不会从 DOM 中删除,而是会变形为新内容。这会保留 DOM 中的节点,并允许保留状态(例如焦点)。 但是,在这两种算法中,在变形两个节点时不考虑兄弟节点的子节点的结构:仅考虑考虑节点。这是由于性能原因:在匹配时递归遍历兄弟姐妹的所有子代是不可行的。

Idiomorph 采用不同的方法:在节点匹配发生之前,新内容和旧内容都会被处理以创建 id 集,即元素到该元素中找到的所有 id 集合的映射。也就是说,元素的所有子元素中的所有 id 的集合,加上元素的 id(如果有)。 Id 集可以通过查询选择器 + 自下而上算法相对有效地计算。 给定 id 集,可以采用比简单地使用 id 匹配更广泛意义上的“匹配”:如果元素 1 和元素 2 的 id 集之间的交集非空,则它们匹配。这使得 Idiomorph 可以根据子级的结构信息相对快速地匹配元素,这些子级为父级的 id 集做出贡献,与简单的基于 id 的匹配相比,可以实现更好的整体匹配。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号