router icon indicating copy to clipboard operation
router copied to clipboard

fix: SSR invariant dehydration errors with bun

Open Cyenoch opened this issue 7 months ago • 10 comments

Related: https://github.com/TanStack/router/issues/3989

The script assigned to __TSR_SSR__.dehydrated appears outside the </html> tag. When the entry script /_build/assets/client-BJoNZ2zg.js is cached locally by the browser, even if the entry script is async, the script outside the html may still be executed after the entry script.

https://github.com/TanStack/router/blob/72ffeb4d4ae23a30859b9c7b8a3164535d5f2b85/packages/start-server-core/src/transformStreamWithRouter.ts#L171

Problems occur when text is complete HTML

https://github.com/TanStack/router/blob/72ffeb4d4ae23a30859b9c7b8a3164535d5f2b85/packages/start-server-core/src/transformStreamWithRouter.ts#L174-L175

https://github.com/TanStack/router/blob/72ffeb4d4ae23a30859b9c7b8a3164535d5f2b85/packages/start-server-core/src/transformStreamWithRouter.ts#L190

bodyEndMatch is assigned before the !headStarted branch processes chunkString.

https://github.com/TanStack/router/blob/72ffeb4d4ae23a30859b9c7b8a3164535d5f2b85/packages/start-server-core/src/transformStreamWithRouter.ts#L216

The length of bodyEndIndex obtained here will exceed the length of the modified chunkString, resulting in <script> being appended after </html>

Image

The solution is make sure hydrate is executed after TSR_SSR.dehydrated is assigned a value by other means.

Cyenoch avatar May 22 '25 09:05 Cyenoch

View your CI Pipeline Execution ↗ for commit 846bf44fa7ca506adbd31ae9e8e8fbd1e0a287b8.

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 1m 37s View ↗

☁️ Nx Cloud last updated this comment at 2025-05-25 09:36:29 UTC

nx-cloud[bot] avatar May 22 '25 16:05 nx-cloud[bot]

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@4228
@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@4228
@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@4228
@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@4228
@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@4228
@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@4228
@tanstack/react-router-with-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-with-query@4228
@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@4228
@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@4228
@tanstack/react-start-config

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-config@4228
@tanstack/react-start-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-plugin@4228
@tanstack/react-start-router-manifest

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-router-manifest@4228
@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@4228
@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@4228
@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@4228
@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@4228
@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@4228
@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@4228
@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@4228
@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@4228
@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@4228
@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@4228
@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@4228
@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@4228
@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@4228
@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@4228
@tanstack/solid-start-config

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-config@4228
@tanstack/solid-start-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-plugin@4228
@tanstack/solid-start-router-manifest

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-router-manifest@4228
@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@4228
@tanstack/start

npm i https://pkg.pr.new/TanStack/router/@tanstack/start@4228
@tanstack/start-api-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-api-routes@4228
@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@4228
@tanstack/start-config

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-config@4228
@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@4228
@tanstack/start-server-functions-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-client@4228
@tanstack/start-server-functions-fetcher

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-fetcher@4228
@tanstack/start-server-functions-handler

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-handler@4228
@tanstack/start-server-functions-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-server@4228
@tanstack/start-server-functions-ssr

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-ssr@4228
@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@4228
@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@4228
@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@4228

commit: 846bf44

pkg-pr-new[bot] avatar May 22 '25 16:05 pkg-pr-new[bot]

I think it would be better if ensure that all tsr-once is before the entry script

Cyenoch avatar May 23 '25 03:05 Cyenoch

I think it would be better if ensure that all tsr-once is before the entry script

that's not possible as values might stream in later

schiller-manuel avatar May 24 '25 20:05 schiller-manuel

how can I reproduce the issue locally?

schiller-manuel avatar May 25 '25 07:05 schiller-manuel

how can I reproduce the issue locally?

For example:

cd example/react/start-material-ui

Update app.config.ts set server.preset = 'bun'

pnpm build

bun run .output/server/index.mjs

Open "localhost:3000" and enter F12 to switch the throttling to 3G

Tap reload button on browser navigation bar, after reloading for about a dozen times (client entry scripts cached in memory), Invariant failed started to appear.

image

image

image

Cyenoch avatar May 26 '25 03:05 Cyenoch

image

Even if tsr-once is in html, Invariant failed will still appear. So I think if this script is before client entry script, the problem should be solved. Or the other way to make sure hydrate is executed after __TSR_SSR__.dehydrated is assigned a value by other means.

Cyenoch avatar May 26 '25 03:05 Cyenoch

Change script loading attribute from async to defer seems to solve this problem

Cyenoch avatar May 26 '25 06:05 Cyenoch

i found the issue, a synchronization error when injecting the scripts. I'll fix this as part of a rewrite of this section.

schiller-manuel avatar May 26 '25 18:05 schiller-manuel

very thankful

Cyenoch avatar May 27 '25 01:05 Cyenoch