Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Styles duplicated across css chunks create source order issues #12343

Closed
petewarman opened this issue Apr 30, 2020 · 42 comments · Fixed by #16134
Closed

Styles duplicated across css chunks create source order issues #12343

petewarman opened this issue Apr 30, 2020 · 42 comments · Fixed by #16134
Assignees
Labels
kind: bug Confirmed bug that is on the backlog
Milestone

Comments

@petewarman
Copy link

Bug report

Describe the bug

I have an application that uses a component on multiple pages. When I build the project that component's styles are duplicated in each of the relevant css page chunks; this creates visual bugs.

For example (some-component, and initial-page-component-override are classes applied to the same element in the DOM on the initial page):

initial-page.chunk.css

// component styles
.some-component { margin-bottom: 10px; }

// page specific override
.initial-page-component-override { margin-bottom: 20px; }

second-page.chunk.css

// component styles
.some-component { margin-bottom: 10px; }

When second-page.chunk.css is added to the DOM the component styles are reapplied over the top of any page specific styles defined in the initial page. The overrides are lost and the incorrect margin is now applied to the component on the initial page. N.B. this is not an issue in dev mode, only in production.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Checkout https://github.com/petewarman/nextjs-css-module-issue
  2. npm i, npm run build, npm start
  3. Hover the cursor over the lime green button
  4. See it change to pink when the second page's stylesheet is preloaded

Expected behavior

Style declarations should not be duplicated in compiled stylesheets. Component styles should loaded (in their own chunk?) above page specific styles.

System information

  • OS: macOS
  • Version of Next.js: 9.3.6
  • Version of Node.js: 10.16.3
@iksent
Copy link

iksent commented Apr 30, 2020

I am having exactly the same problem: #11946 (comment)

@fabinppk
Copy link

Same problem here too 😢
I described my problem here: #11901 (comment)

@EduardoPedrosa
Copy link

Any progress? I still have the same problem and I can't put it into production.
Tested on 9.3.7-canary.9

@fabinppk
Copy link

fabinppk commented May 5, 2020

@EduardoPedrosa
Status: v9.3.7-canary.11 and the problem still persist.

@Timer Timer added this to the 9.3.x milestone May 6, 2020
@sophiekoonin
Copy link

sophiekoonin commented May 12, 2020

We seem to be having a similar problem with components from a shared component library in our monorepo - any styles in our app that affect those components are overridden by the library styles, despite the fact that the specificity of the styles in our app CSS files is higher and therefore should take precedence. It looks fine in dev mode, just not production :(

(We are using SCSS modules with @zeit/next-sass)

image

image

@fabinppk
Copy link

When i was using @zeit/next-sass or @zeit/next-css everything was pretty fine with order, preference and duplicates between chuncks. 🤔

The real problem to me begins when i updated nextjs to 9.3 and started using css modules.

@iksent
Copy link

iksent commented May 14, 2020

I tried both 2 methods (next-sass and built-in) - the problem existed in both cases

@iksent
Copy link

iksent commented May 18, 2020

My Stack:

  1. CSS Modules
  2. SCSS
  3. Dart-Sass with @use imports

Tried a lot of variations and this one works for me (having no styles duplicates):

  1. package.json:
"@zeit/next-css": "^1.0.1",
"@zeit/next-sass": "^1.0.1",
"next": "9.2.1", (9.4.1 is current)
"node-sass": "npm:sass@1.26.2", (this is dart sass, but can be used default)
  1. next.config.js
const path = require('path')
const withSass = require('@zeit/next-sass')
const withCSS = require('@zeit/next-css')
const withBundleAnalyzer = require('@next/bundle-analyzer')({ // Optional, of course
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer(
  withCSS(
    withSass({
      cssModules: true,
      sassLoaderOptions: {
        // Resolving SASS absolute imports
        includePaths: [path.resolve(__dirname, 'src')],
      },
      cssLoaderOptions: {
        importLoaders: 2,
        localIdentName:
          process.env.NODE_ENV === 'production'
            ? '[hash:base64]'
            : '[name]__[local]__[hash:base64:5]',
      },
      webpack(config, options) {
        // Resolving absolute imports
        config.resolve.modules.push(path.join(__dirname, 'src'))

        // Make global styles work
        config.module.rules.forEach(rule => {
          if (rule.test && rule.test.toString().includes('.scss')) {
            rule.rules = rule.use.map(useRule => {
              if (typeof useRule === 'string') {
                return {
                  loader: useRule,
                }
              }

              if (useRule.loader.startsWith('css-loader')) {
                return {
                  oneOf: [
                    {
                      test: new RegExp('.module.scss$'),
                      loader: useRule.loader,
                      options: useRule.options,
                    },
                    {
                      loader: useRule.loader,
                      options: {},
                    },
                  ],
                }
              }
              return useRule
            })
            delete rule.use
          }
        })

        return config
      },
    }),
  ),
)
  1. Importing global (not modules) styles like this:

index.scss:

...
@import '~emoji-mart/css/emoji-mart.css';
...

It will be great, if someone try such a configuration, so I can make sure this really works.

@Timer Timer modified the milestones: 9.4.x, 9.4.2, 9.4.3 May 18, 2020
@Timer Timer modified the milestones: 9.4.3, 9.4.4 May 28, 2020
@MurkyMeow
Copy link

MurkyMeow commented Jun 13, 2020

I suggest replacing this:

.other-page__component-override { background: pink; }

With this:

.other-page .component-override { background: pink; }

So the page-specific styles only apply on that specific page =).

@Timer Timer added the kind: bug Confirmed bug that is on the backlog label Jun 29, 2020
@Timer Timer modified the milestones: 9.4.5, 9.x.x Jun 29, 2020
@p-chan
Copy link

p-chan commented Jul 10, 2020

I'm having trouble with this bug too.
I changed the next-css to built-in css and it happened.
It works in development mode, but it doesn't work in production mode when CSR is used. In SSR, there is no problem.

@kambala3000
Copy link

I use next 9.4.4 with built-in css support and I have this problem too, it happens in production.

@grefrit
Copy link

grefrit commented Jul 10, 2020

Same problem on next 9.4.4. Only in production mode

@Howard86
Copy link

This happens to our production env on next 9.4.4, and somehow we found a solution.

As using node-sass, we try various options from the doc, and solve this by adding a new sassOptions to next.config.js

module.exports = {
  ...,
  sassOptions: {
    outputStyle: 'expanded',
  },
}

Reference: outputStyle

After checking css classname after next build, this seems to be working.
Hope this helps!

@alexandre-marchina
Copy link

alexandre-marchina commented Jul 15, 2020

Thanks for sharing @Howard86, tried but it didn't work here. We are using next-css and next-sass on our builds also (not the built-in CSS support from next, and having the same problem described in this issue), and the duplication occurs in classes coming from pure css imported as css-modules, which not come from sass styles

@fabinppk
Copy link

@Howard86 @alexandre-marchina

I am using built-in CSS from next, next 9.4.4 and your solution also dont worked to me. 😢

@Timer Timer added this to the iteration 7 milestone Aug 10, 2020
@marcin-piela-sf
Copy link

This bug makes using css-modules in next.js impossible (cause no one wants to add !important in styles)

@VictorPivnenko
Copy link

This bug makes using css-modules in next.js impossible (cause no one wants to add !important in styles)

You can bump up specificity for the styles that override the basic styles. For instance, let's have components dependency as Button <- IconButton <- MoreSpecificButton. In this case, Button has its own styles that get reloaded when switching to another page and therefore overrides styles from IconButton and MoreSpecificButton. If IconButton has its styles defined as .className.className, and MoreSpecificButton has its styles as .className.className too then Button won't override it. And having the fact that the order of IconButton and MoreSpecificButton styles is correct in css the styles of MoreSpecificButton will always override IconButton - expected.

@bigtimeyash
Copy link

Experienced the same issues with next v9.5.1 on prod build, on dev build the styles are ok.

I am experiencing the same issue.

@talaikis
Copy link

+1 with Tailwind, Bootstrap. Current workaround is to import all the styles via link rel in the _document.js. For Tailwind it is custom css build. This problem is very annoying.

@lucasmogari
Copy link

lucasmogari commented Aug 11, 2020

I'm using css modules with tailwind (normal global css import). Inlining css solved the load ordering, but I don't know if it is still duplicating, it's just a workaround. In production, I didn't notice a style overriding another.

vercel/next-plugins#238 (comment)

@Timer
Copy link
Member

Timer commented Aug 18, 2020

This is fixed on the latest Next.js canary. Please upgrade to next@^9.5.3-canary.7 and let us know!

@talaikis
Copy link

talaikis commented Aug 18, 2020

Doesn't fix it for me, as an example, line heights, font weights, background colors, borders are different in dev and prod.

@Timer
Copy link
Member

Timer commented Aug 18, 2020

@talaikis please open a new issue with a fully reproducible demo then! I've tested the exact code given in this reproduction and its working on canary now.

@fabinppk
Copy link

Fix to me, but it causes another more critical problem.
In my case when i change only hash url using Router.push(localhost:3000/#change) coming from localhost:3000` all stylesheets reload again causing the screen blink.

@Timer
Copy link
Member

Timer commented Aug 18, 2020

Can you please try 9.5.3-canary.9?

@fabinppk
Copy link

@Timer running npm i:

image

@fabinppk
Copy link

i had try 9.5.3-canary.9 but its still persist problem with hash.

I didn't mention it, but am using 9.5.2 and when i migrated to 9.5.3-canary.6 there is also an error in devtools console when i use router to change hash like above.
The problem dont exist in 9.5.3-canary.5.

image

@Timer
Copy link
Member

Timer commented Aug 19, 2020

@fabinppk please open a new issue with a reproduction!

@petewarman
Copy link
Author

Just wanted to confirm the original issue seems to be fixed in 9.5.3-canary.9. Thank you @Timer

@Timer
Copy link
Member

Timer commented Aug 19, 2020

Thanks for confirming @petewarman!

@fabinppk
Copy link

@Timer sure. I think your fix its ok and its not related with this problem in devtools.
Thank you. 👍

@ghost
Copy link

ghost commented Oct 22, 2020

Can confirm this is still happening with 9.5.6-canary.11, classes get duplicated across chunks.

@fabinppk
Copy link

@glottonous all problems commented in this issues was solved by timer.

Ps: i am using 9.5.5. 👌👌

@ghost
Copy link

ghost commented Oct 23, 2020

@fabinppk I can confirm that the same issue is still happening as of 9.5.6-canary.11.

@fabinppk
Copy link

@glottonous I did some tests on my project with version 9.5.6-canary.11 and I didn't have any problems.

If you are really having a problem, open a new issue by referencing this one. 👍

@ghost
Copy link

ghost commented Nov 3, 2020

in nextjs 10, same issues

@Edward-Fedoruk
Copy link

Same issues 10.0.1

@guilhermehn
Copy link

I've started #19055 with a reproducible demo.

@vercel vercel locked as resolved and limited conversation to collaborators Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind: bug Confirmed bug that is on the backlog
Projects
None yet
Development

Successfully merging a pull request may close this issue.