aidenybai / million

Optimize React performance and make your React 70% faster in minutes, not months.
https://million.dev
MIT License
15.89k stars 558 forks source link

Hydration and other errors in next 14 + million 3 #971

Closed BarakChamo closed 4 months ago

BarakChamo commented 4 months ago

What version of million are you using?

3.0.3

Are you using an SSR adapter? If so, which one?

Vercel

What package manager are you using?

bun

What operating system are you using?

Mac

What browser are you using?

Arc

Describe the Bug

Following the automatic setup for million@3.0.3, I'm getting hydration errors with next@14.1.0 that are not there when million is removed.

This is the configuration for million in my next.config.mjs:

const millionConfig = {
    auto: {
        mute: true,
        threshold: 0.05, // default: 0.1,
        skip: [
            // 'useBadHook', /badVariable/g
        ],
        rsc: true,
    },
}

Issue 1 - JSX comments

This one is pretty straightforward, in the current configuration million can't handle JSX comments, throwing a flurry of webpack errors.

Very basic example:

This works:

        <main>
            <div>
                <p>examples/basic</p>
                <div>
                    <a
                        href="https://vercel.com?utm_source=create-turbo&utm_medium=basic&utm_campaign=create-turbo"
                        rel="noopener noreferrer"
                        target="_blank"
                    >
                    </a>
                </div>
            </div>
        </main>

This breaks:

        <main>
            <div>
                <p>examples/basic</p>
                <div>
                    <a
                        href="https://vercel.com?utm_source=create-turbo&utm_medium=basic&utm_campaign=create-turbo"
                        rel="noopener noreferrer"
                        target="_blank"
                    >
                        {/* <Image alt="Vercel Logo" className={styles.vercelLogo} height={24} priority src="/vercel.svg" width={100} /> */}
                    </a>
                </div>
            </div>
        </main>

Issue 2 - SSR Hydration

The second issue is hydration errors that only come up when enabling millions.

I can't offer a very simple reproduction yet, but what I can share is the following error:

Unhandled Runtime Error
Error: Hydration failed because the initial UI does not match what was rendered on the server.

Warning: Did not expect server HTML to contain a <div> in <slot>.

See more info here: https://nextjs.org/docs/messages/react-hydration-error

Component Stack
slot
MillionBlock
../../node_modules/million/dist/packages/react.mjs (131:36)
eval
../../node_modules/million/dist/packages/react.mjs (289:74)
NavBar
./src/app/landing/components/NavBar.tsx (149:80)
div
div

This suggests that millions components inserted in auto mode area breaking hydration as there is a mismatch between sent markup and client code.

Happy to provide more information following the discussion.

What's the expected result?

Issue 1

million should be able to handle components that are commented out.

Issue 2

million components such as <slot/> and <block/> should not break SSR hydration process.

Link to Minimal Reproducible Example

https://million.dev/

Participation

github-actions[bot] commented 4 months ago

Thanks for opening this issue! A maintainer will review it soon.

Aslemammad commented 4 months ago

Hey @BarakChamo, do you have any stackblitz reproduction?

henrituan commented 4 months ago

For the hydration issue, I managed to work around by forcing my component to render client side. I'm using Page router so I have to do this:

import dynamic from 'next/dynamic';

const Component = () => {...}

export const MyComponent = dynamic(
  () => Promise.resolve(Component ),
  {
    ssr: false,
  },
);

For App router, I suppose use client is enough

Aslemammad commented 4 months ago

Yes, a repro would be ideal! I'll try it tomorrow, but if you had any repro, it'd make my job as a maintainer so much easier :)

BarakChamo commented 4 months ago

@Aslemammad encouragingly I was not able to reproduce the issue (for comments) on Stackblitz easily so I suppose it's something in my project's particular configuration.

FWIW, our project is set up as a next.js monorepo, using latest next.js and million. I'll create an exact repro with the same tsconfig and next config but would be great to know which other potential configs affect million compilation so I know to include these.

We're in a bit of a release crunch so will attempt a proper repro later this week and share it.

@henrituan that's great to know there's a workaround, I suppose this would work for client-side leaf nodes but this would not be a viable solution for, say, top-level providers that wrap entire routes or layouts.

Is hydration a known issue?

Aslemammad commented 4 months ago

Yeah, around which configs affect the compilation, @lxsmnsyc is much more informative on the compile part, so he might give some insight.

And around the reproduction, I would be happy to wait for it so I can find a solution if possible.

khuezy commented 4 months ago

I'm also experiencing the hydration issue. I don't have a repro unfortunately, I just noticed that when I do next dev --turbo, it doesn't have any problems... but when I remove the --turbo flag, I can reproduce it locally via next dev

Aslemammad commented 4 months ago

I'll check soon with a nextjs 14 sample, hope I can reproduce it.