-
Notifications
You must be signed in to change notification settings - Fork 328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include layout for Turbo-Frame:
requests
#232
Conversation
72b9134
to
6777a72
Compare
The bandwidth benefits of optimizing `Turbo-Frame:` header responses to omit the layout do not offset the HTTP-layer cache busting trade-offs. Similarly, there's an opportunity to implement behavior changes related to: * [@hotwired/turbohotwired#361][] * [@hotwired/turbohotwired#257][] if both `<turbo-frame>` elements' `FrameController` instances and `Session` instances were able to share `Visit` instances built from fully formed `<html>` pages. By trimming the layout and outer portions of the document, `turbo-rails` forces frames to deal with incomplete fragments. [@hotwired/turbohotwired#257]: hotwired/turbo#257 [@hotwired/turbohotwired#361]: hotwired/turbo#361
6777a72
to
f56024c
Compare
I like the idea of simplifying things, but there are more considerations than just bandwidth. There's also the price of producing the request server side. Like the cost to produce the layout itself. But... that cost is paid everywhere else, so is that enough? I'd like to verify this on our apps though. Also, there's the slight regression in readability on the return when you're debugging. It's been very nice just to see the frame that changed. |
Closes hotwired#229 --- Mark the request's [variant][] as `:turbo_frame` whenever the `Turbo-Frame:` header is present in the request. Also adds documentation to describe how to achieve the previously built-in layout optimizations. [variant]: https://guides.rubyonrails.org/4_1_release_notes.html#action-pack-variants
dd6fb31
to
d0a7661
Compare
If hotwired/turbo#398 is viable, it'd be simpler to traffic in full HTML documents. If there's interest to support It would be possible with only fragments, but committing to transmitting full HTML documents as responses has other upsides that make it seem worthwhile. This is, of course, only a requirement for frames that drive the browser's history. If applications or frames aren't interested in that, they can opt-into the bare It would be easier to opt-in for scenarios that need it than it is to reverse the existing default behavior of never sending a full document response. |
So been thinking about this some more. I don't think layout-by-default is going to give us any caching advantages, because most turbo frames are used/loaded exclusively for that purpose. They're rarely used directly. At least that's the usage across all of HEY for us. Furthermore, many layouts are actually pretty big. For HEY, now that we're going with import maps, there's a lot of stuff in the head. Don't want to keep shipping that across all the time. |
# This is merely a rendering optimization. Everything would still work just fine if we rendered everything including the layout. | ||
# Turbo Frames knows how to fish out the relevant frame regardless. | ||
# When the <tt>Turbo-Frame</tt> header is present, the request's <a | ||
# href="https://guides.rubyonrails.org/4_1_release_notes.html#action-pack-variants">variant</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# href="https://guides.rubyonrails.org/4_1_release_notes.html#action-pack-variants">variant</a> | |
# href="https://guides.rubyonrails.org/layouts_and_rendering.html#the-variants-option">variant</a> |
Something that maybe hasn't been noted yet: At the moment if you set |
# <tt>html+turbo_frame.erb</tt> extension that renders | ||
# without the navigation and layout elements: | ||
# | ||
# <%= app/views/layouts/application.html+turbo_frame.erb %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# <%= app/views/layouts/application.html+turbo_frame.erb %> | |
# <%# app/views/layouts/application.html+turbo_frame.erb %> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to generate this view as part of the install generator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly would be in this layout? Seems like we would need a way to customize the turbo_frame_id here if it wraps the rendered content with a turbo_frame, but I am not sure that is the intent.
Ahhh, sorry, I meant if you do something like this class ApplicationController
layout "my_layout_view"
end Then that overrides the layout that This PR fixes it though so that's cool. Also you can just take the stuff in this PR and copy it into your own app (which I did yesterday and it worked great). |
For what it's worth, the The behavior mentioned in #232 (comment) relies on the variant portion of these changes more than reverting the |
I've opened hotwired/turbo#445 to introduce the In some cases, (like in the case of a That capability is contingent on the response being a fully formed HTML document. There's also an ongoing discussion about providing applications with the ability to "break out" of a frame. The proposed version of that feature would also depend on the response to a request with the |
@dhh @seanpdoyle I have implemented a module that, when included in a controller, dynamically determines the layout. This way you can use standard templates and either wrap them in a turbo_frame or wrap them in the application layout, depending on what kind of request it is. The module is here: https://github.com/WriterZephos/TurboRouter/blob/main/lib/turbo_router/controller.rb I am curious if this is born out of a misunderstanding and if there is an official way to do this, or if the PR is meant to provide an official way. Also, it seams like the changes proposed by @ghiculescu would break the pattern I implemented, and as I stated before I think there is real benefit from not rendering the layout by default, since most turbo_frame requests will be intended to render partials. My 2 cents from someone trying to figure out the right patterns for this stuff. |
So I think setting a layout globally SHOULD override the current behavior. I think if you want to set a layout in a more nuanced way, you need a before action such as what was proposed above or something like the pattern I implemented here where layout is a proc: https://github.com/WriterZephos/TurboRouter/blob/main/lib/turbo_router/controller.rb |
Chiming in here in favor of rendering with the layout (or at least making this configurable). If you have a layout that uses a -if content_for(:sidebar)
= yield :sidebar If I try to render a turbo response with a template that captures the |
I don't think doing the layout for all turbo requests is the right trade-off as a default. But I'd be happy to take a way, or perhaps just documentation, to let people tweak this for an individual app. Let's explore that in a new PR, though. |
A new edge case has been uncovered that hasn't been mentioned in this discussion: when responding to a form submitted from within a For example, a controller action "ending" with respond_to do |format|
format.html { redirect_to(...) }
format.turbo_stream
end would respond with a Turbo Stream content type, and that response would surprisingly omit a layout. If the |
Wouldn't this fly: respond_to do |format|
format.html { redirect_to(...) }
format.turbo_stream { render layout: "something" }
end ? |
Same problem as @seanpdoyle regarding form submission @dhh yes it would (and it works), but then, we would have to put the "render layout" every time? Or is there a better way? [Edit] I found a way, if you add this line in your application_controller.rb :
Then, the application.turbo_stream layout is loaded for every turbo stream request. |
Re-submission of [hotwired#232][] Related to [hotwired/turbo#1047][] Render full documents, including default layout rendering behavior. Rendering a minimal layout forces `turbo:reload` events because of the severe difference in the contents of the minimal layout's `<head>` and the requesting document's fully populated `<head>`. [hotwired#232]: hotwired#232 [hotwired/turbo#1047]: hotwired/turbo#1047
Re-submission of [hotwired#232][] Related to [hotwired/turbo#1047][] Render full documents, including default layout rendering behavior. Rendering a minimal layout forces `turbo:reload` events because of the severe difference in the contents of the minimal layout's `<head>` and the requesting document's fully populated `<head>`. [hotwired#232]: hotwired#232 [hotwired/turbo#1047]: hotwired/turbo#1047
Re-submission of [hotwired#232][] Related to [hotwired/turbo#1047][] Render full documents, including default layout rendering behavior. Rendering a minimal layout forces `turbo:reload` events because of the severe difference in the contents of the minimal layout's `<head>` and the requesting document's fully populated `<head>`. [hotwired#232]: hotwired#232 [hotwired/turbo#1047]: hotwired/turbo#1047
Re-submission of [hotwired#232][] Related to [hotwired/turbo#1047][] Render full documents, including default layout rendering behavior. Rendering a minimal layout forces `turbo:reload` events because of the severe difference in the contents of the minimal layout's `<head>` and the requesting document's fully populated `<head>`. [hotwired#232]: hotwired#232 [hotwired/turbo#1047]: hotwired/turbo#1047
Re-submission of [hotwired#232][] Related to [hotwired/turbo#1047][] Render full documents, including default layout rendering behavior. Rendering a minimal layout forces `turbo:reload` events because of the severe difference in the contents of the minimal layout's `<head>` and the requesting document's fully populated `<head>`. [hotwired#232]: hotwired#232 [hotwired/turbo#1047]: hotwired/turbo#1047
Include layout for
Turbo-Frame:
requestsThe bandwidth benefits of optimizing
Turbo-Frame:
header responses toomit the layout do not offset the HTTP-layer cache busting trade-offs.
Similarly, there's an opportunity to implement behavior changes related
to:
if both
<turbo-frame>
elements'FrameController
instances andSession
instances were able to shareVisit
instances built fromfully formed
<html>
pages. By trimming the layout and outer portionsof the document,
turbo-rails
forces frames to deal with incompletefragments.
Mark variant as
turbo_frame
when header presentCloses #229
Mark the request's variant as
:turbo_frame
whenever theTurbo-Frame:
header is present in the request. Also adds documentationto describe how to achieve the previously built-in layout optimizations.