-
Notifications
You must be signed in to change notification settings - Fork 478
turbo:load fires very late when Turbo is loaded with defer (misses interactive state) #1492
Description
When Turbo is loaded using defer, the turbo:load event can fire very late (close to window.onload) because Turbo only triggers it in response to readystatechange transitions.
If Turbo initializes after the document has already reached readyState = "interactive", it misses that transition and waits until "complete" instead.
This causes JS that depends on turbo:load to be delayed until all deferred/async scripts finish loading, which can block page interactivity.
Why this matters
We migrated from Turbolinks → Turbo, and this regression started appearing after the migration.
turbolinks:loadfired onDOMContentLoaded- It worked reliably even when Turbolinks itself was deferred
- With Turbo, deferring the script can unintentionally tie
turbo:loadtoreadyState = "complete"/window.onload
In real production cases, this has caused:
- Frozen or non-interactive UI
- Navigation blocked for users
Root cause (as I understand it)
Turbo triggers turbo:load only when it observes readystatechange changes (interactive or complete).
It does not check the current document.readyState when initializing.
So if Turbo loads after interactive, it will always wait for complete.
Questions
- Is this behavior intentional / expected when Turbo is deferred?
- Is Turbo expected to work correctly when loaded using defer, or is synchronous loading assumed?
- Is there a recommended event for “DOM ready + Turbo-safe initialization” that doesn’t depend on
readyState = "complete"? - Would it make sense for Turbo to trigger
turbo:loadimmediately ifdocument.readyStateis already"interactive"?
Thanks for the great work on Turbo 🙏