Skip to content

[Turbopack] React fails to hydrate in cross-origin WebView (Android) — regression from 16.1.7 to 16.2.0 #94075

@AriajSarkar

Description

@AriajSarkar

Link to the code that reproduces this issue

https://github.com/AriajSarkar/nextjs-webview-hydration-repro

To Reproduce

  1. Create a Next.js App Router project with output: "export" and assetPrefix pointing to a network IP
  2. Load the app in a WebView from a cross-origin context (e.g., Tauri v2 Android dev mode, where the WebView loads from http://192.168.x.x:3000 while the dev server runs on 0.0.0.0:3000)
  3. Observe that on Next.js 16.0.10, React hydrates correctly — useEffect fires, onClick handlers work, HMR may fail but the app is interactive
  4. Upgrade to Next.js 16.2.6 — React never hydrates. The server-rendered HTML displays, but no client-side JavaScript takes effect

Minimal next.config.ts:

const internalHost = process.env.TAURI_DEV_HOST || "localhost";

const nextConfig = {
  output: "export",
  images: { unoptimized: true },
  assetPrefix: `http://${internalHost}:3000`,
};

export default nextConfig;

Minimal page.tsx:

"use client";
import { useEffect, useState } from "react";

export default function Home() {
  const [hydrated, setHydrated] = useState(false);

  useEffect(() => {
    console.log("React hydrated!");
    setHydrated(true);
  }, []);

  return (
    <div>
      <p>{hydrated ? "✅ Hydrated" : "⏳ Waiting..."}</p>
      <button onClick={() => alert("clicked!")}>Click me</button>
    </div>
  );
}

Current vs. Expected behavior

Expected Behavior

React should hydrate and become interactive even when the HMR WebSocket connection fails (cross-origin context). The initial page load and hydration should not depend on a successful HMR WebSocket handshake. This was the behavior in Next.js 16.0.10.

Actual Behavior

On Next.js 16.2.6, Turbopack's module loader appears to get stuck waiting for the HMR WebSocket connection. Since the connection cannot be established from the cross-origin WebView, React's client-side code never executes, and the page remains a static HTML shell with no interactivity.

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Home Single Language
  Available memory (MB): 16069
  Available CPU cores: 16
Binaries:
  Node: 25.9.0 // nvm-version
  npm: 11.12.1
  Yarn: N/A
  pnpm: 10.19.0
Relevant Packages:
  next: 16.0.10 // There is a newer version (16.2.6) available, upgrade recommended! 
  eslint-config-next: N/A
  react: 19.2.6
  react-dom: 19.2.6
  typescript: 5.9.3

Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

When running next dev with Turbopack (default in Next.js 16) and loading the app inside a cross-origin Android WebView (via Tauri v2), React never hydrates on Next.js 16.2.6. The same setup works perfectly on 16.0.10.

What happens:

  • Server-rendered HTML appears in the WebView ✅
  • The React runtime chunk loads (React DevTools suggestion message appears in Tauri/Console logcat) ✅
  • useEffect never fires
  • onClick handlers never attach ❌ — buttons are visible but dead
  • Native HTML elements (textarea) still accept input because they don't require React
  • No JavaScript errors appear in the WebView console — the failure is completely silent

Evidence from adb logcat:

# This appears (React runtime loaded):
I Tauri/Console: File: http://192.168.1.7:3000/_next/static/chunks/073a_next_dist_....js
  Msg: %cDownload the React DevTools...

# This NEVER appears (useEffect never fires):
# [expected] I Tauri/Console: ... Msg: React hydrated!

Context:

  • The WebView loads from http://192.168.1.7:3000 (network IP)
  • The dev server listens on 0.0.0.0:3000
  • assetPrefix is set to http://192.168.1.7:3000
  • The HMR WebSocket likely fails to connect (cross-origin), but on 16.0.10 this doesn't prevent hydration — React still mounts and becomes interactive
  • On 16.2.6, the Turbopack module loader appears to block on the failed WebSocket connection, preventing client-side JavaScript from executing

Comparison with working project:

I have another project (Tin) using the exact same Tauri + Next.js + App Router + output: "export" setup but pinned to Next.js 16.0.10. It works perfectly in Android dev mode — React hydrates, events work, everything is interactive. The only significant difference is the Next.js version.

Working (Tin) Broken (A4Chat)
Next.js 16.0.10 16.2.6
React 19.2.1 19.2.6
output "export" "export"
assetPrefix http://${ip}:3000 http://${ip}:3000
Hydration ✅ Works ❌ Silent failure

Metadata

Metadata

Assignees

No one assigned

    Labels

    TurbopackRelated to Turbopack with Next.js.

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions