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

Missing support for HotWire Turbo Drive, successor of turbolinks #482

Open
mildred opened this issue Feb 17, 2021 · 7 comments
Open

Missing support for HotWire Turbo Drive, successor of turbolinks #482

mildred opened this issue Feb 17, 2021 · 7 comments

Comments

@mildred
Copy link

mildred commented Feb 17, 2021

When my turbo drive page reloads, the profiler information is removed. This did not happen when I was using turbolinks.

Most things should work the same, just replace turbolinks by turbo.

@mildred
Copy link
Author

mildred commented Feb 19, 2021

I tried replacing turbolinks with turbo in includes.js but it is not working. I don't understand how it is supposed to work. As far as I understand the implementation, this is what happens when a turbolink visit happens:

  • a visit happens, turbo loads asynchronously the new page and extract the body
  • the body is replaced and because the includes.js script is not marked with data-turbo-permanent="true", the script is removed from the page and a new script is inserted
  • MiniProfiler include.js script is loaded anew and initialized again
  • because upon reinitialization, MiniProfiler does not patch XMLHttpRequest nor window.fetch again, it performs only partial initialization
  • XMLHttpRequest and window.fetch are patched using the previous instance of MiniProfiler, and when a query is made, it functions as usual. Only, MiniProfiler is adding profiling results to a container that is disconnected from the page DOM

Over the time, MiniProfiler is initialized many times. I believe that it should be marked with data-turbo-permanent="true" to avoid multiple instances of the same script in memory, and conflicting callbacks referring to disconnected instances but still living in some ways. The other thing to do is to reconnect the container to the page body if MiniProfiler detects it is no longer connected (because Turbo removed it from the page)

@mildred
Copy link
Author

mildred commented Feb 19, 2021

My experiments now involved initialization in rails:

  module RackTurboExtension
    def get_profile_script(*args, **kargs)
      super(*args, **kargs).gsub('></script>', ' data-turbo-permanent="true"></script>')
    end
  end

  module Rack
    class MiniProfiler
      prepend RackTurboExtension
    end
  end

and in javascript:

document.addEventListener("turbo:before-visit", e => {
  window.MiniProfilerContainer = document.querySelector('body > .profiler-results')
  if(!e.defaultPrevented) window.MiniProfiler.pageTransition()
})

document.addEventListener("turbo:load", e => {
  if(window.MiniProfilerContainer) {
    document.body.appendChild(window.MiniProfilerContainer)
  }
})

@kbrock
Copy link
Contributor

kbrock commented Jun 1, 2021

Bonjour Mildred,

Have you tried putting the code into the actual source code as a PR?

both look pretty straight forwards (though to be honest I'm more of a back end developer than a front end one)

@ceritium
Copy link
Contributor

ceritium commented Jun 11, 2021

@mildred, I created a PR based on your solution. Can you take a look? Thanks!

#498

@nickjj
Copy link

nickjj commented Apr 2, 2022

Hi,

#498 works wonderfully for Turbo Drive but there's still the case of using Turbo Streams and maybe Turbo Frames.

When you respond with a stream the profiler will auto-increment the response times. For example it will say 10ms for the first request, 20ms for the 2nd, 30ms for the third, etc. and only gets "fixed" if you manually do a hard reload. You can test this by submitting a form and responding with a stream in your controller. This makes it hard to tell what the true response time is for a stream response which in a Rails 7 app could be every single form submission.

@technicalpickles
Copy link
Contributor

I think there is something missing still. I tried adding to a brand new app (which uses hotwire/turbo by default), added a few scaffolds. It seems that the profiler goes missing after the first click (ie when using turbo), but comes back when you do a reload.

I see this place where hotwire support is detected, but I haven't been able to trace where data-turbo-permanent gets set 🤔

@jnimety
Copy link

jnimety commented Jan 13, 2024

There is a race condition between buttonShow(json) in the request.onload callback and when onTurboBeforeVisit calls window.MiniProfiler.pageTransition() to cleanup the old profiles. When window.MiniProfiler.pageTransition() happens to run first everything is fine. When buttonShow(json) runs first the new profile will immediately get removed by pageTransition(). I really have no idea how to fix this but hopefully it helps someone else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants