next.js: CSS modules duplicated when used with `next/dynamic`

What version of Next.js are you using?

10.2.2

What version of Node.js are you using?

14.16.0

What browser are you using?

Chrome

What operating system are you using?

macOS

How are you deploying your application?

Vercel

Describe the Bug

When using next/dynamic with CSS modules, we’ve found that CSS can be re-inserted (duplicated)

In our scenario, we have a simple <Text /> component that is already in use throughout the application. When we used <Text /> in a new component that was dynamically imported, styles for <Text /> were re-inserted.

These styles were inserted below all other styles, breaking some styles that rely on specificity - which is how we found this bug.

As a temporary workaround, we’ve removed that component from the dynamically loaded component.

Expected Behavior

Styles should not be re-inserted/duplicated.

To Reproduce

We haven’t been able to reliably reproduce this in a standalone repo.

We’ve looked and found some potentially similar issues, and this might be related: https://github.com/vercel/next.js/issues/20203.

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 36
  • Comments: 27 (2 by maintainers)

Most upvoted comments

The same issue without using dynamic. next@13.2.4

I’m wondering why this problem persists for a few years and a lot of tickets was closed without any solution.

We’re also experiencing this with Next@13.1.5.

image

And it’s not reproducing running locally with next dev, which makes it even worse given the fact that we need to double-check such issues by building “prod” version locally OR just observing it when it gets to QA env (which uses “prod” version).

I can actively reproduce it without dynamic.

  • Create a shared component outside of app directory.
  • Create two or more pages that utilize the shared component.
  • Notice that the shared component has duplicate styles.

Even if you have not visited both pages, if you have a Link component ( or something else that preloads the other page ). The server will stream down two css files, both with the EXCACT same selectors.

The browser for good reason can’t dedup css selectors, instead it essentially does a merge. Ultimately I am just worried about the performance hit here, since it is doing the dedup on basically every shared component. Its also messy to read and a bad dev experience.

Hope this helps 😃

12.1.6 still has problem : Capture d’écran 2022-06-09 à 00 04 51

Next.js v12.1.0 still has problem.

I’m getting duplicate css without using dynamic.

I have the same issue in next@13.5.6 even without dynamic imports. Seriously this problem has been going on for so long and it still hasn’t been fixed?

Any updates here? Have the same issue with next@13.4.7

image

Experienced this issue in 12.3.1 and found a workaround.

TL;DR: add a hidden (display: none should work) div in App/Page. In this div render all the components that have their styles duplicated.


Explanation: webpack (or whatever) seems to check whether components used in a dynamic import are already present on the page. In my case everything was fine when a loadable component was imported on a specific page. Later I moved the component to _app.tsx and styles started to duplicate in the CSS file emitted for the loadable component.

Say you have a few components:

  • App (pages/_app.tsx)
  • Page (pages/index.tsx)
  • Button (components/button.tsx)
  • LoadableModal (components/loadable-modal.tsx)
  • LoadableModal uses Button

* uses means imports either directly or indirectly but without dynamic imports.

The issue may be reproduced in a few ways:

  1. LoadableModal is used in App, Button is used in Page (sure, tested)
  2. LoadableModal is used in Page, Button is used in App (not sure, need to test)
  3. Button is used neither in Page nor in App. There is an additional LoadableForm component that uses Button used on the same page. (not sure, need to test)

When building Next.js checks imports to see whether components used in dynamic are already present on the page. Since the relation between Page and App is not direct there is no way for it to detect that the Button is already used.

My workaround was the following: add a hidden (display: none should work) div in App/Page. In this div render all the components that have their styles duplicated. With this fix in place Next.js should properly deduplicate styles.

Perhaps it is also possible to not render the component at all by using {false && <Button />}.

I am encountering a similar issue - CSS modules are getting duplicated and overwritten for similar components on a page - e.g. implementations of a custom <Button /> component - after one of these components is dynamically loaded. No issue when the conditional dynamic component is not loaded. There’s a clear flash of changing styles once the dynamic component is loaded.

Update: was initially on next@11.1.2, updating to v12.0.2 didn’t fix this issue.

This bug is present even without using next/dynamic

I have the same issue with next@13.4.17. Any workarounds so far?

Repo to reproduce this: https://github.com/PepeBotella25/css_module_dynamic_issue

Initially image

After adding dynamic component using the same “shared” component image

Since you need css chunks to reproduce it you have to do build+start

npm run build
npm run start

When second component get added its css brings the “shared” styles again affecting the cascade order: image