Skip to content

Compatibility With Hotwire Turbo

Naofumi Kagami edited this page Sep 12, 2022 · 3 revisions

Since both Hotwire/Turbo and Next.js use different SPA technologies, there are minor issues when transitioning between these pages.

You can test this demo site with Turbo on by commenting out Turbo.session.drive = false; in app/javascript/application.js.

Turbo page to Next.js page transition

The following is what happens when you transition from a Hotwire/Turbo page to a Next.js page

  1. The user is currently on a page rendered by Turbo. They click on a link that takes them to a Next.js page.
  2. Turbo sends an XMLHTTPRequest request for new page, with the expectation that it will receive an ERB rendered HTML response with the same <head> element.
  3. Since the URL for the new page is actually rendered by Next.js, the response will be HTML with a completely different <head> element.
  4. On receiving the response, Turbo recognises the difference and realises that this is not a Turbo response. It gives up on processing the transition in SPA mode. Instead, it requests a second, full page load for the new URL.
  5. Next.js renders the new page again and sends it back to the browser.
  6. The browser displays the new page.

This will cause the page transition to be long and show a blank page mid-way. The transition can be made smoother by switching off Turbo globally so that the first XMLHTTPRequest will not be attempted. If you would like to maintain SPA behaviour for Turbo to Turbo transitions, then you can alternatively switch off Turbo for each individual link.

Next.js page to Turbo page transition

  1. From a page rendered in Next.js, the user clicks on a link that takes them to an ERB rendered page.
  2. I do not fully understand how Next.js does this, but instead of making an XMLHTTPRequest, it directly makes a request for a full page load.

As a result, Next.js page to Turbo page transitions are smoother than Turbo to Next.js.

I suspect that Next.js can do this because it has full knowledge of what routes it can serve. Turbo on the other hand does not have this information, and only realises that the new URL is not Turbo after sending an XMLHTTPRequest and receiving the response.