多个模型是否可共用同一个turbo_stream_from标签?有何弊端?
合并Turbo Stream共享流的弊端说明
使用多个turbo_stream_from标签的常规独立流写法如下:
<%= turbo_stream_from "posts" %> <div id="posts">...</div> <%= turbo_stream_from "comments" %> <div id="comments">...</div> # Post模型逻辑 broadcast_update_to "posts", target: self # Comment模型逻辑 broadcast_update_to "comments", target: self
有开发者会尝试把两个独立数据流合并为一个共享流,写法如下:
<%= turbo_stream_from "unified_stream" %> <div id="posts">...</div> <div id="comments">...</div> # Post模型逻辑 broadcast_update_to "unified_stream", target: self # Comment模型逻辑 broadcast_update_to "unified_stream", target: self
这种写法不是不能跑,但存在几个很实际的弊端:
- 带宽和性能的无意义消耗:只要订阅了这个统一流,不管当前页面需不需要对应内容更新,所有广播到这个流的消息都会推送到客户端。比如用户打开的是只展示帖子列表、根本没有评论区的页面,也会收到所有评论的更新推送,平白占用带宽,前端也要额外处理这些根本用不上的消息,数据量大了之后页面延迟会非常明显。
- 权限管控容易出漏洞:独立流可以针对不同资源单独做订阅权限校验,比如帖子流校验帖子访问权限、评论流单独校验评论可见范围。合并成统一流之后,权限校验粒度会变粗,很容易出现漏判:比如用户本来无权查看某条私密评论,结果因为统一流只做了帖子权限校验,私密评论的更新就会直接推给用户,造成数据泄露。
- 后期维护和迭代非常麻烦:所有资源的广播都走同一个通道,后续要加限流、消息过滤、异常熔断这类逻辑的时候,没办法单独针对某一类资源做配置,很容易改一处影响全量功能。出问题排查的时候,也很难快速定位到底是哪类资源的广播逻辑出了错。
- 无效DOM操作拖慢页面响应:Turbo Stream收到消息后会在整个页面查找对应target的DOM节点,就算当前页面根本没有评论容器,收到评论更新消息时也会遍历全量DOM找目标节点,页面结构复杂的时候,这类无效操作积少成多很容易造成页面卡顿。
如果是逻辑极简单、两类资源完全绑定、没有权限差异的微型页面,这种合并写法确实能少写一行代码省点事,但只要项目有后续迭代的可能,都不建议用这种合并流的方案。
内容的提问来源于stack exchange,提问作者Justin Tanner
相关产品推荐
相关产品推荐

