Skip to content
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

Double fetch requests for eager-loaded frames #515

Closed
blrB opened this issue Jan 20, 2022 · 8 comments · Fixed by #516
Closed

Double fetch requests for eager-loaded frames #515

blrB opened this issue Jan 20, 2022 · 8 comments · Fixed by #516

Comments

@blrB
Copy link
Contributor

blrB commented Jan 20, 2022

I think I found a bug.

Steps to reproduce:

  1. Create page with eager-loaded frame
  2. Create link with redirect on this page (HTTP code not important)
  3. Click on link for get redirect
  4. Watch browser network tab (or sever logs)

Example requests for turbo_frame with id: src_content:
Chrome:
chrome_duplicate_requests
Firefox:
ff_duplicate_requests

All my 'eager-loaded frames' were loaded twice. You can look part of my source code for ruby 3.1.0, rails 7.0.1, turbo-rails 1.0.1 here: https://gist.github.com/blrB/1b0e1d44f31df1d1c9932985471ec3b3

I think, that root case can be in line https://github.com/hotwired/turbo/blame/main/src/core/drive/visit.ts#L274 (commit 38b8f13). Now redirect responses use visit action replace. This visit create next trace start -> ... -> loadResponse -> render -> ... -> replaceBody -> sourceURLChanged -> loadSourceURL -> fetch request for frame. But fetch request already was created and rendered, before replace action had been created. I think we shouldn't render this action twice, so we can just create this action with prams willRender: false. I tested this code, and I think it works like I expected. You can look source code here: #516

@blrB blrB changed the title Double fetch request for eager-loaded frames Double fetch requests for eager-loaded frames Jan 20, 2022
@john-kelly
Copy link

I’m running into this as I’m upgrading from turbolinks.

As a question for the maintainers of the project, is this intended/expected behavior? I imagine others have run into this and I couldn’t find any official statements or documentation regarding this behavior.

My rough understanding is that things changed once turbo started using fetch - and therefore could handle redirects.

Thanks so much for documenting this issue @blrB. And thank you to the turbo maintainers.

@dhh
Copy link
Member

dhh commented Mar 30, 2022

Going off memory here, I think the issue is that the snapshot that's showed first before the page is fetched again triggers the frame loading. Thus you end up with the double loads. If that's still the case, then it seems like we need to figure out how to make the snapshots permanent with the frames all loaded. I think maybe @seanpdoyle have had a look at this in the past?

@dhh dhh closed this as completed in #516 Jun 19, 2022
@seanpdoyle
Copy link
Contributor

I believe a change like the one made in #487 might help resolve this issue. It proposes a [loaded] attribute (there are some additional considerations regarding the name), which would expose a frame's load state in a cache-friendly way.

seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Aug 9, 2022
When redirecting to a page that contains elements marked with
`[data-turbo-cache="false"]`, those elements are removed _before_ the
initial render, instead of _after_ the render and _before_ the page is
cached.

This behavior seems to have stemmed from [hotwired#516][], which
was shipped in response to [hotwired#515][].

As an alternative to the `willRender: false` option passed to
`this.adapter.visitProposedToLocation` in `Visit.followRedirect`, the
implementation can instead [rely on the presence of the
`turbo-frame[complete]`][comment] to guard against double fetching.

To guard against regressions, this commit adds coverage for the unwanted
behavior by redirecting from `navigation.html` to `cache_observer.html`,
and asserting the presence of a `[data-turbo-cache="false"]` element
that resembles and application's Flash messaging.

[hotwired#515]: hotwired#515
[hotwired#516]: hotwired#516
[comment]: hotwired#515 (comment)
[hotwired#487]: hotwired#487
seanpdoyle added a commit to seanpdoyle/turbo that referenced this issue Aug 9, 2022
When redirecting to a page that contains elements marked with
`[data-turbo-cache="false"]`, those elements are removed _before_ the
initial render, instead of _after_ the render and _before_ the page is
cached.

This behavior seems to have stemmed from [hotwired#516][], which
was shipped in response to [hotwired#515][].

As an alternative to the `willRender: false` option passed to
`this.adapter.visitProposedToLocation` in `Visit.followRedirect`, the
implementation can instead [rely on the presence of the
`turbo-frame[complete]`][comment] to guard against double fetching.

To guard against regressions, this commit adds coverage for the unwanted
behavior by redirecting from `navigation.html` to `cache_observer.html`,
and asserting the presence of a `[data-turbo-cache="false"]` element
that resembles and application's Flash messaging.

[hotwired#515]: hotwired#515
[hotwired#516]: hotwired#516
[comment]: hotwired#515 (comment)
[hotwired#487]: hotwired#487
dhh pushed a commit that referenced this issue Aug 11, 2022
When redirecting to a page that contains elements marked with
`[data-turbo-cache="false"]`, those elements are removed _before_ the
initial render, instead of _after_ the render and _before_ the page is
cached.

This behavior seems to have stemmed from [#516][], which
was shipped in response to [#515][].

As an alternative to the `willRender: false` option passed to
`this.adapter.visitProposedToLocation` in `Visit.followRedirect`, the
implementation can instead [rely on the presence of the
`turbo-frame[complete]`][comment] to guard against double fetching.

To guard against regressions, this commit adds coverage for the unwanted
behavior by redirecting from `navigation.html` to `cache_observer.html`,
and asserting the presence of a `[data-turbo-cache="false"]` element
that resembles and application's Flash messaging.

[#515]: #515
[#516]: #516
[comment]: #515 (comment)
[#487]: #487
@blrB
Copy link
Contributor Author

blrB commented Oct 19, 2022

Hello. I try use turbo-rails (1.3.1), but this issue still presents. I can't understand how #674 resolve this issue. I see that frame has complete attribute, but it is still make two fetch request.

@seanpdoyle, could you please help me with this?

image
image

@blrB
Copy link
Contributor Author

blrB commented Oct 21, 2022

Also this issue can be reproduce in test fixtures page (http://localhost:9000/src/tests/fixtures/frames.html), after click link "Eager-loaded frame after GET redirect":

turbo

Unfortunately, the written tests did not fail during the regression run(((

line this.assert.equal(fetchLogs.length, 1) for test "test navigating a eager frame with a link[method=get] that does not fetch eager frame twice" works incorrect, due to fetchLogs variable has two elements and test should be failed:

[
  [
    'turbo:before-fetch-request',
    {
      fetchOptions: [Object],
      url: 'http://localhost:9000/src/tests/fixtures/frames/frame_for_eager.html',
      resume: undefined
    },
    'eager-loaded-frame'
  ],
  [
    'turbo:before-fetch-request',
    {
      fetchOptions: [Object],
      url: 'http://localhost:9000/src/tests/fixtures/frames/frame_for_eager.html',
      resume: undefined
    },
    'eager-loaded-frame'
  

Instead of this, test marks as passed. It is strange. It is look like assert.equal() method not works at all.

image
image

@seanpdoyle
Copy link
Contributor

seanpdoyle commented Oct 21, 2022

@blrB thank you for continuing to pull on this thread.

Unfortunately, the written tests did not fail during the regression run

I've cut a branch that resolves the broken assertion issues, and causes the test you wrote to fail:

https://github.com/hotwired/turbo/compare/seanpdoyle:frame-test-broken-assertion

The willRender: false option you introduced in #516 was eventually reverted by 256418f, but the silently failing test did not catch the regression.

@dhh could you re-open this issue?

@blrB are you interested in continuing to experiment with a solution?

@blrB
Copy link
Contributor Author

blrB commented Oct 21, 2022

@seanpdoyle thank you for response

are you interested in continuing to experiment with a solution?

Yes, I try to check your alternative option described in 256418f on next week.

@blrB
Copy link
Contributor Author

blrB commented Feb 5, 2023

#779 (comment)

Issue doesn't reproduce on the main branch.

@blrB blrB closed this as completed Feb 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants