Hydration error when using Turbopack with dynamically imported named exports.
Link to the code that reproduces this issue
https://github.com/gurkerl83/next-turbo-dynamic-import
To Reproduce
- Clone the reproduction repository:
git clone https://github.com/gurkerl83/next-turbo-dynamic-import.git
- Install dependencies using pnpm:
pnpm install
- Run the development server with Turbopack:
pnpm dev:turbo
- 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:
- Works with both Webpack and Turbopack (direct file path import)
const ComponentDirectImport = dynamic(
() => import("@module/first/src/SimpleComponent")
);
- 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.
Hi @gurkerl83, I'm here to check in, does it work when using as { default: module.SimpleComponent }?
@devjiwonchoi I will try with the latest canary version later today, and keep you updated.
@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!
Hi @gurkerl83 ,
I can see the same error in the web page
The above error in the screenshot is related to your issue?please let me know.
@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
Moreover I can see the error on initial page load once we refresh the page the error has gone!
ss:
@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 even though I tried uninstalling concerned extensions it still showing error in the console after the refresh its gone.
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 🙏
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!
Is there a fix for this yet ? or has a new issue been created ?
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
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 please read my previous messages, further messages on this issue will be hidden as spam as they're irrelevant for the issue @gurkerl83 reported.
okay @timneutkens
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!
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 👍🏽
I'm having the same issue (double rendering) but only when my dynamic component is using the { ssr: true } option.
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.
For me, this doesn't resolve the problem. I still have a double-rendered component.
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.