TanStack / TanStack/devtools

data-tsd-source inject-source plugin causes hydration mismatch in SSR (TanStack Start)

Abierto Apto para principiantes
#405 0 comentarios 4 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Lenguaje dominante
TypeScript
Estrellas
499
Forks
100
Merge medio
1 d 17 h
PR fusionados (30 d)
4

Descripción

Description

The inject-source plugin in @tanstack/devtools-vite causes React hydration mismatch warnings in TanStack Start (SSR) projects. The data-tsd-source attributes are injected with different line numbers on the server vs client transform passes, because other Vite plugins (e.g. tanstackStart(), viteReact()) shift line numbers differently between SSR and client bundles.

Reproduction

  1. Create a TanStack Start project with @tanstack/devtools-vite v0.6.0
  2. Add devtools() to vite.config.ts
  3. Navigate to any SSR-rendered route
  4. Observe console warning:
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties.

<div
+ data-tsd-source="/src/routes/simulations/$slug/editor.tsx:632:5"
- data-tsd-source="/src/routes/simulations/$slug/editor.tsx:636:5"
>

Line numbers are consistently off by a fixed offset (4 lines in my case) — the server and client transforms produce different source locations for the same JSX elements.

Root Cause

In plugin.ts, the inject-source Vite plugin's apply function only checks config.mode === 'development':

apply(config) {
  return config.mode === 'development' && injectSourceConfig.enabled
},

The transform hook does not check the ssr boolean that Vite passes as the third argument. Since data-tsd-source is only useful on the client (for click-to-source in the devtools UI), injecting it during the SSR pass creates the mismatch.

Suggested Fix

Skip source injection during the SSR transform pass. The Vite transform hook receives { ssr: boolean } as the third argument:

transform(code, id, options) {
  if (options?.ssr) return; // Only inject on client
  // ... existing Babel transform
}

This would eliminate the hydration mismatch while preserving click-to-source functionality on the client.

Workaround

Disable source injection entirely:

devtools({ injectSource: { enabled: false } })

This removes the hydration warning but loses click-to-source in the devtools UI.

Environment

  • @tanstack/devtools-vite: 0.6.0
  • @tanstack/react-start: latest
  • React 19
  • Vite 7

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza en plugin.ts e inspecciona el hook transform del plugin de Vite inject-source, incluida la opción ssr que pasa Vite. Omite la inyección de código fuente para las transformaciones SSR, manteniendo la inyección del lado del cliente; después, verifica que el desajuste de hidratación informado ya no se produzca y que click-to-source siga disponible.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
react, typescript
Área
devtools
Tipo de issue
Error
Dificultad
2/5
Tiempo estimado
1-3 horas
Estado de actividad
Tranquilo
Claridad
Bien especificado
Aptitud para principiantes
78/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.