next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Hydration error when using Turbopack with dynamically imported named exports.

Open gurkerl83 opened this issue 1 year ago • 3 comments

Link to the code that reproduces this issue

https://github.com/gurkerl83/next-turbo-dynamic-import

To Reproduce

  1. Clone the reproduction repository:
git clone https://github.com/gurkerl83/next-turbo-dynamic-import.git
  1. Install dependencies using pnpm:
pnpm install
  1. Run the development server with Turbopack:
pnpm dev:turbo
  1. Observe the console for hydration issues.

Current vs. Expected behavior

Current Behavior:

  • Webpack (pnpm dev): The application runs without issues, and both dynamically imported components (direct import and named export import) render as expected.
  • Turbopack (pnpm dev:turbo): The component that uses a named export (module.SimpleComponent) results in a hydration error. The browser console shows a hydration mismatch between the server-rendered HTML and the client-side React tree.

Expected Behavior:

  • The components should hydrate correctly with both Webpack and Turbopack.
  • No hydration errors should occur when using dynamically imported named exports.

Examples:

  1. Works with both Webpack and Turbopack (direct file path import)
const ComponentDirectImport = dynamic(
  () => import("@module/first/src/SimpleComponent")
);
  1. Works with Webpack but causes hydration error with Turbopack (dynamic import with named export)
const ComponentNamedImportWithIssue = dynamic(() =>
  import("@module/first").then((module) => module.SimpleComponent)
);

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.5.0: Wed May  1 20:17:33 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6031
  Available memory (MB): 65536
  Available CPU cores: 16
Binaries:
  Node: 22.6.0
  npm: 10.8.2
  Yarn: N/A
  pnpm: 9.11.0
Relevant Packages:
  next: 15.0.0-canary.177 // Latest available version is detected (15.0.0-canary.177).
  react: 19.0.0-rc-0751fac7-20241002
  react-dom: 19.0.0-rc-0751fac7-20241002
  typescript: 5.6.2
Next.js Config:
  output: N/A

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

Lazy Loading, Pages Router, Turbopack

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

next dev (local)

Additional context

  • The hydration error occurs only when using Turbopack with dynamically imported named exports.
  • The problem is triggered when using .then() after a dynamic import to access a named export (import("@module/first").then((module) => module.SimpleComponent)).
  • The project uses React's latest release candidate version (19.0.0-rc-0751fac7-20241002) and Next.js's latest canary version (15.0.0-canary.177).
  • I tested the application against the latest canary release, also against previous versions.
  • Direct imports do not cause the same issue, which suggests that the problem is related specifically to the way Turbopack handles named exports within dynamic imports.

gurkerl83 avatar Oct 04 '24 14:10 gurkerl83

Hi @gurkerl83, I'm here to check in, does it work when using as { default: module.SimpleComponent }?

devjiwonchoi avatar Oct 17 '24 07:10 devjiwonchoi

@devjiwonchoi I will try with the latest canary version later today, and keep you updated.

gurkerl83 avatar Oct 17 '24 08:10 gurkerl83

@devjiwonchoi I tried with the latest canary versions of both next and react. I have updated the reproducer with these versions.

 "next": "15.0.0-canary.196",
 "react": "19.0.0-rc-77b637d6-20241016",
 "react-dom": "19.0.0-rc-77b637d6-20241016"

Putting it on default when importing like the following, also fails with the canary versions mentioned.

const ComponentNamedImportWithIssue = dynamic(() =>
  import("@module/first").then((module) => ({
    default: module.SimpleComponent,
  }))
);

The closest I could find in the set of open PRs, which maybe is related is, but this is just a guess. https://github.com/vercel/next.js/pull/71145

Can you please forward this issue to one of the engineers, who are working on the turbopack feature.

Thx!

gurkerl83 avatar Oct 17 '24 10:10 gurkerl83

Hi @gurkerl83 , I can see the same error in the web page
image The above error in the screenshot is related to your issue?please let me know.

Susheel4115 avatar Oct 30 '24 14:10 Susheel4115

@devjiwonchoi @gurkerl83 I am also getting this hydration error, not sure if this is related to this thread, just created new project using latest nextjs version with turbopack

Screenshot 2024-10-30 at 7 32 55 PM

qasimgit avatar Oct 30 '24 14:10 qasimgit

Moreover I can see the error on initial page load once we refresh the page the error has gone! ss: image

Susheel4115 avatar Oct 30 '24 14:10 Susheel4115

@Susheel4115 @qasimgit I'd recommend opening another issue because these don't look related based on the screenshot. It looks like you just have a generic hydration error caused by e.g. a chrome extension installed in your browser.

Please make sure that when posting comments you're not sharing screenshots but instead share the actual code. A great example of a good and useful interaction is @gurkerl83's investigating and providing a reproduction in this issue.

timneutkens avatar Oct 30 '24 14:10 timneutkens

@timneutkens even though I tried uninstalling concerned extensions it still showing error in the console after the refresh its gone.

Susheel4115 avatar Oct 30 '24 14:10 Susheel4115

I'd love to help you but I can't help you if you don't share the code that reproduces the issue 🙂 Please open a new issue 🙏

timneutkens avatar Oct 30 '24 15:10 timneutkens

I tried to make the description as clear as possible.

The hydration error is caused when using these in combination.

  • turbopack
  • next/dynamic
  • named exports from a module

Hydration errors can be caused by many reasons, this particular one is only forming when these conditions are met.

@Susheel4115 I also guess that you have some kind of extension interfering, other reasons might be a secondary react installation in your node modules, but this might be only the case when you are linking libraries by hand after compiling them. Take a fresh browser installation an see if the error persists. The reproducer I provided shows the hydration error even on refresh. Hope this helps.

Thx!

gurkerl83 avatar Oct 30 '24 17:10 gurkerl83

Is there a fix for this yet ? or has a new issue been created ?

H4LV3D avatar Oct 30 '24 17:10 H4LV3D

A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:

- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.

https://react.dev/link/hydration-mismatch

  ...
    <Router actionQueue={{state:{...}, ...}} assetPrefix="">
      <HistoryUpdater>
      <RuntimeStyles>
      <HotReload assetPrefix="">
        <ReactDevOverlay state={{nextId:1, ...}} dispatcher={{...}}>
          <DevRootNotFoundBoundary>
            <NotFoundBoundary notFound={<NotAllowedRootNotFoundError>}>
              <NotFoundErrorBoundary pathname="/" notFound={<NotAllowedRootNotFoundError>} notFoundStyles={undefined} ...>
                <RedirectBoundary>
                  <RedirectErrorBoundary router={{...}}>
                    <Head>
                    <link>
                    <script>
                    <script>
                    <RootLayout>
                      <html
                        lang="en"
-                       coupert-item="9AF8D9A4E502F3784AD24272D81F0381"
                      >
``` there is embedded gemini ai thing(not an extension) which has a statement - 
The error "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties" in your React application, triggered by the line originConsoleError.apply(window.console, args), likely stems from the fact that you're using a server-side rendered (SSR) component and attempting to access a client-side object (window.console) within it. This violates the principle of hydration, where the server-rendered HTML is expected to match the client-side rendering.

Here's a breakdown of why this happens and how to fix it:

Server-Side Rendering (SSR): When SSR is used, the initial HTML is generated on the server. The server doesn't have access to the window object, which is a browser-specific global object. Therefore, any code that relies on window will either fail or produce different output on the server than on the client.
Hydration Mismatch: React's hydration process compares the server-rendered HTML with the client-side rendered component tree. If there are discrepancies, hydration fails, leading to the error you're seeing. In your case, the server likely rendered something different than the client due to the window.console reference.
originConsoleError.apply(window.console, args): This line attempts to use the browser's console object (window.console) on the server. Since window is undefined on the server, this will either throw an error or produce a different result, causing the hydration mismatch.
Solutions:

Conditional Rendering: The most straightforward solution is to conditionally execute the code that uses window.console only on the client-side 

Susheel4115 avatar Oct 31 '24 04:10 Susheel4115

When I tried running localhost:3000/ in incognito chrome the error no more persists I think we have to create a new issue for hydration error occurs when extensions like react dev tools and vue dev tools, are installed.

Susheel4115 avatar Oct 31 '24 04:10 Susheel4115

@Susheel4115 please read my previous messages, further messages on this issue will be hidden as spam as they're irrelevant for the issue @gurkerl83 reported.

timneutkens avatar Oct 31 '24 10:10 timneutkens

okay @timneutkens

Susheel4115 avatar Nov 05 '24 11:11 Susheel4115

Hi @timneutkens,

It’s been a while! I know there’s a lot happening with Turbopack, but I was wondering if one of the developers might be able to take a look at the issue. I’ve retested this with the latest Canary versions:

"next": "15.0.4-canary.28"
"react": "19.0.0-rc-7670501b-20241124"
"react-dom": "19.0.0-rc-7670501b-20241124"

Unfortunately, the problem persists. The recent changes related to dynamic/import don’t seem to have resolved it yet.

Thanks so much for your help!

gurkerl83 avatar Nov 26 '24 00:11 gurkerl83

Hi @gurkerl83,

Glad to see your message I have cloned the code repo using your provided url and while I try to debug the code I came across this piece of code :

loadableOptions = { ...loadableOptions, ...options }

const loaderFn = loadableOptions.loader as () => LoaderComponent<P> const loader = () => loaderFn != null ? loaderFn().then(convertModule) : Promise.resolve(convertModule(() => null))

I can understand there is a problem with names export that too in turbopack please check the code I have provided if there is any leads please let me I know I found this issue is interesting 👍🏽

Susheel4115 avatar Nov 26 '24 04:11 Susheel4115

I'm having the same issue (double rendering) but only when my dynamic component is using the { ssr: true } option.

ryrybeal13 avatar Dec 18 '24 20:12 ryrybeal13

The problem is fixed in 15.1.1-canary.14, most likely here https://github.com/vercel/next.js/commit/d3529bad5dec9794270e5479fdb5eab5108247fb.

Important note: 15.1.1-canary.14 is newer then 15.1.2, so make sure you specify 15.1.1-canary.14 or newer.

gurkerl83 avatar Dec 19 '24 23:12 gurkerl83

For me, this doesn't resolve the problem. I still have a double-rendered component. image

ryrybeal13 avatar Dec 20 '24 15:12 ryrybeal13

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

github-actions[bot] avatar Jan 04 '25 00:01 github-actions[bot]