MiniProfiler / rack-mini-profiler

Profiler for your development and production Ruby rack apps.
MIT License
3.7k stars 402 forks source link

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

Open mildred opened 3 years ago

mildred commented 3 years ago

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 commented 3 years ago

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:

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

https://github.com/MiniProfiler/rack-mini-profiler/pull/498

nickjj commented 2 years ago

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 commented 10 months ago

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 commented 7 months ago

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.