vercel / next.js

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

Duplication of CSS rules #42082

Open whiteand opened 1 year ago

whiteand commented 1 year ago

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022
Binaries:
  Node: 16.17.0
  npm: 8.15.0
  Yarn: 1.22.19
  pnpm: 7.13.0
Relevant packages:
  next: 14.2.0-canary.21
  eslint-config-next: 14.1.3
  react: 18.2.0
  react-dom: 18.2.0

What browser are you using? (if relevant)

Chrome 106.0.5249.119

How are you deploying your application? (if relevant)

Vercel

Describe the Bug

Page has different styling depending on HOW we get to the page.

When we go to the page from other page - we get one style. When we refresh page we have different color.

The only difference is "Does link to the /lazy page was rendered before rendering /to page or not"

When link to /lazy page is not rendered before. /to page has appropriate styles with red background. When link to /lazy page is rendered before. /to page will have inappropriate styles.

Expected Behavior

/to page should have exact same styles regardless of how we go to this page

Link to reproduction

https://github.com/whiteand/next-js-css-order-bug

To Reproduce

Steps to reproduce:

I expect that regardless of the ways we go to the /to page background will be red.

whiteand commented 1 year ago

In Next.js v13.0.2 still not fixed

whiteand commented 1 year ago

Still not fixed in next@13.0.6-canary.2

whiteand commented 1 year ago

Still not fixed in next@13.1.2-canary.1

whiteand commented 1 year ago

Still not fixed in next@13.1.3-canary.0

uaeio commented 1 year ago

Still not fixed in next@13.1.3-canary.4

uaeio commented 1 year ago

Still not fixed in next@13.1.6-canary.1

whiteand commented 1 year ago

still not fixed in next@13.1.7-canary.0

whiteand commented 1 year ago

still not fixed in next@13.1.7-canary.10

uaeio commented 1 year ago

Still not fixed in next@13.2.4-canary.0

uaeio commented 1 year ago

Still not fixed in next@13.2.5-canary.3

uaeio commented 1 year ago

Still not fixed in next@13.2.5-canary.12

whiteand commented 1 year ago

Still not fixed in next@13.3.1-canary.3

whiteand commented 1 year ago

Still not fixed in 13.3.1-canary.6

uaeio commented 1 year ago

Still not fixed in 13.4.11-canary.2

ananevandrei11 commented 1 year ago

Still not fixed 13.1.6

nodegin commented 11 months ago

This is breaking my tailwind rules, please fix it

whiteand commented 11 months ago

Still not working in: 13.4.20-canary.23

Rudi-Batubara commented 11 months ago

Still not fixed in: v13.5.3

whiteand commented 10 months ago

Still not fixed in next@13.5.5-canary.12

doug-stewart commented 9 months ago

Still experiencing it in 14.0.1.

whiteand commented 8 months ago

Still not fixed in 14.0.4-canary.37

doug-stewart commented 8 months ago

For anyone who comes to this but I can at least explain how I "solved" it in my projects.

My team uses Bulletproof React's file structure and as part of that all of our feature folders used to use index.ts files for easy importing and use of the feature. Well if something imported from that index it imported all components even if they weren't used.

I can't find any information about how to avoid this issue, what configuration changes would need to be made to avoid it. In the end we just stopped using index files and that solved it. Though I maintain tree shaking should have handled that.

romiem commented 8 months ago

I too can confirm that in my project, removing the index files (which were being used to consolidate imports of components) and using direct imports fixes the issue. These components are all client-side components (not sure if that is a factor or not). Also found this reddit thread in which another user had similar success using direct imports:

https://www.reddit.com/r/nextjs/comments/17lonpq/component_styles_duplicating_in_both_layoutcss/

That said, it is not a solution I like, due to the amount of boilerplate that gets added into my imports. In fact, I would rather live with the added payload these duplicated css rules add to my compiled output than change to direct imports.

Hoping that this gets resolved soon because this issue has dragged on for quite some time.

zecka commented 8 months ago

I also have the same issue on next 14.0.4 with css module. I encounter the same issue with vanilla-extract.

Here a reproduction link github: https://github.com/zeckaissue/next-css-duplicated codesandbox: https://codesandbox.io/p/github/zeckaissue/next-css-duplicated/main?workspaceId=08c0217d-10c7-486d-a55b-8417490cf07b

In my example <Demo> component is used in both layout RSC component and inside a client component on page. <Demo2 /> component is use on layout RSC and page RSC. <Demo> css rules are duplicated across page.css and layout css. But <Demo2> css are only into layout.css

image image

Heres is other thread that seems to be related

layout.tsx

import { Demo } from './components/demo'
import { Demo2 } from './components/demo2'
export default function RootLayout({ children}}) {
  return (
    <html lang="en">
      <body>
        <header><Demo /><Demo2 /></header>
        {children}
      </body>
    </html>
  )
}

page.tsx

import { ClientExample } from "./components/client-example";
import { Demo2 } from './components/demo2'
export default function Home() {
  return (
    <main >
      <div>
        <ClientExample /><Demo2 />
      </div>
    </main>
  )
}

client-example.tsx

'use client'
import { Demo } from "./demo"
export const ClientExample = () => {
    return <div>
        Demo inside client component:
        <Demo />
    </div>
}

demo.tsx

import democss from './demo.module.css'
export const Demo = () => {
    return <div className={democss.demo}>Demo</div>
}

demo2.tsx

import demo2css from './demo2.module.css'
export const Demo2 = () => {
    return <div className={demo2css.demo2}>Demo2</div>
}
zecka commented 8 months ago

Other observations

Not related to nextjs version

From what I understand, nextjs generates one css file per page and per layout. If componentA is used on PageA and PageB, the css of componentA will end up on the css of pageA and the css of pageB. In the case of a server component, if CompoentA is used on layout and on pageA, nextjs will remove the css of componentA from the css of pageA. Why isn't the same true for a client component?

Issue is visible on nextjs.org

nextjs.org seems to have the exact same issue in production. Check button style: screenshot

Issue visible on vercel.com

screenshot

Same issue in other framework

This maybe not a real bug. Maybe it's an impossible challenge with code splitting. I have another project build with nuxt2 and scss (in vue component), And this project is also affect by duplicate css rules.

zecka commented 6 months ago

14.1.1-canary.43 seems to fix this issue on my demo repo. I will try with other project later and send feedback here: https://github.com/vercel/next.js/releases/tag/v14.1.1-canary.43

PR that seems to made the fix: https://github.com/vercel/next.js/pull/61198

whiteand commented 5 months ago

@zecka it still does not work in my demo (next@14.2.0-canary.21)

Demo: https://next-js-css-order-bug.vercel.app/from Code: https://github.com/whiteand/next-js-css-order-bug

uaeio commented 4 months ago

Still not fixed in next@14.2.0-canary.56

maazakn commented 2 months ago

I encountered the same issue in Next 14.2.3.

I'm overriding the styles component that belongs to a third-party package, and its HTML is not accessible. To address this, I created a styles.css file and imported it into my wrapper component. The styles are being overridden, but when I inspect the element, I see that the styles are getting duplicated. Interestingly, when I use this component only once (although that's not the case), the duplication no longer occurs since it's being imported or used within the app only once.

Some have suggested that it's an import issue and can be resolved if the component is not imported from the index file. However, this solution isn't working for me, or perhaps I'm doing something wrong.

I understand that this is not the ideal solution, but as a workaround, I've started importing CSS files at the root level, such as in the root layout of Next.js.

whiteand commented 2 months ago

Still not fixed in next@15.0.0-canary.12