vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.89k stars 26.97k forks source link

Unevenly repetitive style in nextjs 14 and later. #58907

Open dincerpece opened 11 months ago

dincerpece commented 11 months ago

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/nextjs-loop-style-fb-1-thfxmv

To Reproduce

The more mantine components added, the more it increases unevenly. If 2 styles are added to the Mantine button component, for example, this becomes 4 in the Mantine carousel. This example is simple and in my own locale it is fixed as 4 styles, in 13.5.6 it remains fixed as 2 styles. Versions 14 and later are also proliferating unevenly. There is an uneven increase, sometimes 5 and sometimes 12, on page refresh.

nextjs version 13.5.6 13-5-6

nextjs version 14 and later... 14-0-3_6 14-0-3_10 14-0-3_12

Current vs. Expected behavior

I waited for it to be fixed in the latest Canary version, but the result is the same. While 2 fixed styles were added in Nextjs 13.5.6, the proliferation continues in later versions.

Verify canary release

Provide environment information

Copyright (C) Microsoft Corporation. All rights reserved.
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.0.4-canary.16
  eslint-config-next: 14.0.4-canary.16
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.2
Next.js Config:
  output: N/A

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

Not sure

Additional context

I'm running it locally, I haven't distributed it anywhere.

youminkim commented 11 months ago

I have same issue and found that this might be related to this code.

const cache = createEmotionCache({ key: 'mantine', prepend: true });
useServerInsertedHTML(() => (
    <style
      data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
      dangerouslySetInnerHTML={{
        __html: Object.values(cache.inserted).join(' '),
      }}
    />
  ));
dincerpece commented 11 months ago

I have same issue and found that this might be related to this code.

const cache = createEmotionCache({ key: 'mantine', prepend: true });
useServerInsertedHTML(() => (
   <style
     data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
     dangerouslySetInnerHTML={{
       __html: Object.values(cache.inserted).join(' '),
     }}
   />
 ));

Yes, that's what it's about. This problem occurs after nextjs 13.5.6. This is how it starts to repeat.

There is no need for emotion like this in Mantine 7. I tried it and it is very stable, but when I upgraded NextJS in my previous projects, it is necessary to switch to Mantine 7 to avoid these problems. This is annoying and sad. I hope it gets fixed.

youminkim commented 11 months ago

In my case, I had multiple component which use the useServeInsertedHTML code and removed all except one. It is not optimal but still working fine. I use Mantine 5 + nextjs 14.0.3

LuisGilGB commented 11 months ago

Not sure if related; but in the app I'm trying to migrate to the App Router, where I'm combining Material UI (which also uses emotion) and Tailwind styles, prepend: true works in development builds; but not in production builds.

I'm using the useServerInsertedHTML and @layer workaround suggested by MUI docs (that's why it's working for development builds). My purpose is to make Tailwind classes to prevail over MUI classes; but in a production build the MUI classes are the ones getting preference in same specificity cases.

Versions:

I'll try to come up with an isolated reproduction and some triage.

dmitrc commented 8 months ago

@LuisGilGB, were you able to find any workarounds to make Tailwind classes prevail?

LuisGilGB commented 8 months ago

@mui/material introduced a new component for integration with Next JS at v5.15. Apart from a nice cut in size in my setup at _app/root layout files, I got that issue fixed.

If using emotion without MUI, I guess that the source code of that component might provide a useful insight.

(Editing later to add the proper links)