We are starting to use Hotwire in our application. The idea is to use a combination of frames and streams to keep the information on the users screen up to date. Our application is multi tenant and one tenant can have multiple users with different permissions. Streaming all updates to all users is therefore not possible.
Our current approach involves starting multiple streams for a user based on their permissions. When we broadcast changes for an entity, we need to make very sure we broadcast to the right stream to prevent data leaking to unauthorised users.
I believe there is an opportunity for Turbo to make this situation easier and less prone to errors. Turbo Frames are already capable of loading their content. You can even reload the content by setting the
url attribute. What if a Turbo Stream is capable of reloading the content of a frame:
<turbo-stream action="reload" target="dom_id"> </turbo-stream>
This has several advantages:
- With multiple users for a tenant, you can still have one stream per tenant. The
dom_iddoesn’t leak sensitive information.
- We leverage the permission checks done in the initial request. When a
dom_idis on the page, we can safely assume the information can also be reloaded without leaking information. Furthermore, the request to the frame’s URL will do another permission check.
- When broadcasting an entity after a change, you never know if the user is on a page with the entity present. With lazy loading frames, the user might be on the right page, but the content might never need loading. By postponing the rendering to the frame request, we never render and broadcast unused HTML.
There are some downsides as well:
- Instead of only the websocket broadcast, one or more extra HTTP requests are needed to reload the frames on a page. This can cause a slight delay in reloading the content on the page.
- Not all frames have a
srcattribute because some are rendered inline. This can be tackled by allowing a
srcattribute and marking the frame as
<turbo-frame id="message_123" src="/messages/123" loaded="true"> Real message content, not a placeholder </turbo-frame>
- Some reloadable frames might not be exposed by a URL. Broadcasting changes doesn’t require a URL for each entity, reloading through frames does.
I’m looking forward to hear if frame reloads through streams is interesting enough to add to Turbo. I’d love to open a PR with the changes!