Closed delitescere closed 2 years ago
Could you share a use case that you have in mind to help demonstrate this feature's utility?
There seems to be some confusion between concepts.
A <turbo-stream>
represents a single DOM operation, and disappears once it's connected to the page.
The @hotwired/turbo-rails
package's <turbo-cable-stream-source>
is a persistently connected element. Its [channel]
and [signed-stream-name]
attributes are forwarded to the Rails application's underlying Action Cable connection. Action Cable does not yet support connecting over EventSource
instances, or ActionController::Live
integration. My hunch is that the channel
and stream-name
attributes are serving the purpose of a ws://
or wss://
web socket URL at a different layer of abstraction.
Since the <turbo-cable-stream-source>
element is declared in @hotwired/turbo-rails
, that repository might be a better place to open an Issue. If your use case is outside of Rails, I'm interpreting the scope of the Issue as much larger, including the introduction of a backend agnostic version of the <turbo-cable-stream-source>
.
Am I misinterpreting anything here?
Yes, this has nothing to do with Rails, the turbo-rails package, nor any server-side code. This is something entirely for @hotwired/turbo.js
on the client side, just like a <turbo-frame>
, &c.
In the case the <turbo-stream>
custom element is present in a response entity of type text/vnd.turbo-stream.html
, the treatment of the element would not change.
This proposal is for allowing the use of the same custom element in a HTML page (of type text/html
) such that the turbo
library would process it in a declarative manner in order to open a Turbo Stream, replacing the need for imperative, error-prone JavaScript.
The likely placement of the <turbo-stream src="...">
element when used this way would be as a child of <head>
element, as that is where the imperative JavaScript incantation would currently go too.
Your "seems to be some confusion between concepts" comment indeed mirrors my "need not (but may) be conflated with" thought ;-)
Thank you for clarifying. Could you share some code or pseudo code to demonstrate the utility?
Presuming the turbo-stream were rendered in the HTML on the server side, what value is there in making an additional HTTP request to the src URL? Would rendering the element directly with contents suffice?
I think you're still confused? This isn't about the content of a turbo-stream, this is about connecting to a turbo-stream.
Without Rails, how do you currently get a browser to connect to an EventStream (or WebSocket) that contains TurboStream content?
You add this to the page (that could be a static HTML file) that's going to receive that stream and have parts of its DOM updated by Turbo:
<head>
<script>
(window['EventSource'] && window['Turbo']) ?
Turbo.connectStreamSource(new EventSource('/my-turbo-stream')) :
console.warn('Turbo Streams over SSE not available');
</script>
</head>
<body>
<div id="some_target_of_my_turbo_stream"><div>
</body>
All this feature request proposes is to remove the need for the <script>
tag and its contents, replacing it with something Hotwire-esque and declarative:
<head>
<turbo-stream src="/my-turbo-stream" />
</head>
<body>
<div id="some_target_of_my_turbo_stream"><div>
</body>
That <turbo-stream>
tag is processed by @hotwire/turbo.js
at the same time as <turbo-frame>
elements (on DOMContentLoaded) to do the same thing as the JavaScript it would replace, along with checking the URL scheme to decide whether to open a WebSocket or an EventStream.
Does calling it <turbo-stream-connection src="/my-turbo-stream" />
make it more obvious (albeit wholly unnecessary otherwise)?
Thank you for sharing that code, I think we're aligned now.
To re-contextualize a part of my original comment:
If your use case is outside of Rails, I'm interpreting the scope of the Issue as much larger, including the introduction of a backend agnostic version of the turbo-cable-stream-source.
I think we're still discussing the details of a backend agnostic version of the turbo-cable-stream-source element. Based on your code sample, I'm interpreting that you're suggesting the current turbo-stream element be extended. Is that correct?
I think overloading the element to behave differently based on the presence or absence of a src attribute could be tricky. Maybe a new turbo-stream-source element (like the Rails version, but without the "cable") could serve that single purpose.
Is there something about extending the semantics and behavior of the existing turbo-stream element that's more compelling than introducing a new element?
I've opened https://github.com/hotwired/turbo/pull/415 to implement this. @delitescere Could you weigh in there on whether or not it fits your use case?
I appreciate it might be tricky, indeed.
To me, it’s the same duality as “turbo-frame acting as a source” and “turbo-frame acting as a target”.
But if it were named slightly differently, that is less important than having it at all. Of course, as I’m not writing it, I defer to the developers to choose the smoothest implementation.
Much appreciated!
Also see https://link.medium.com/hcGxj0262jb for more (a lot more) context
Currently, some JavaScript is needed to connect a Turbo Stream to an EventSource (SSE) or WebSocket (by the way, the docs aren't very clear about how to do this).
It would be superb if it could be done without JavaScript, rather using an incantation of the
turbo-stream
custom element.Current imperative mechanism:
Suggested declarative mechanism:
If the URL scheme was
ws:
then Turbo would create a newWebSocket
, otherwise it would be anEventSource
.The addition of a
src
attribute to the customturbo-stream
tag need not (but may) be conflated with the use of it in directives to altering the DOM as content arrives on the stream or as the result of a form submission (i.e. the existing capabilities of the custom tag).