Dynamic import of SSR components is causing the CSS of all components to be loaded
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.4k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/pferreirafabricio/nextjs-bug-css-modules
To Reproduce
We can reproduce the issue in 2 ways:
Development mode
- Clone the project
- Run
npm install - Start the dev server with:
npm run dev
With production build
- Clone the project
- Run
npm install - Build the app:
npm run build - Run the app from the build:
npm run start
Current vs. Expected behavior
Context: I have a project with its own sections dynamically loaded from a CMS. Each page has a structure defined by a user, and we render it with Next.js based on that structure.
So what I wanted to do is, based on that array of sections, dynamically get the component and render it, but this is not working as expected, since all the CSS and the JS of these components are being loaded in every page, even if the page doesn't use that actual component/section.
Therefore, the expected behaviour is that only the CSS of the components being used in the page is loaded.
In development mode, if you open the page http://localhost:3000/products/1 you will see that 2 CSS files are loaded:
The first one is okay because it's just all the Tailwind CSS classes and configurations. But the second one is not, because on this page I only imported the Button component (via the dynamic import component, as you can see here app/products/[id]/page.tsx), and what I see is the CSS for all of my components:
Now, if you open the http://localhost:3000/blog/1 you will see 2 files as well.
The first one is okay too, because it's from Tailwind CSS. However, on this page, I have only the CSS from the components that I've imported in this page (in this case, a custom Link component, as you can see here app/blog/[slug]/page.tsx):
When running with a production build, the scenario is even worse, because now, even on the blog page, all the CSS of all components is being loaded:
This same behavior happens with both of the pages, blog and product.
Provide environment information
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Pro
Available memory (MB): 32286
Available CPU cores: 20
Binaries:
Node: 22.14.0
npm: 10.9.2
Yarn: 1.22.22
pnpm: 10.24.0
Relevant Packages:
next: 16.0.6 // There is a newer version (16.0.7) available, upgrade recommended!
eslint-config-next: N/A
react: 19.2.0
react-dom: 19.2.0
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
CSS, Lazy Loading, Performance, Turbopack
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local), Vercel (Deployed)
Additional context
I'm using Tailwind CSS with CSS modules to do the styling.
I already tried a variety of approaches for the dynamic-section component, but all of them resulted in the same weird behaviour, including:
- Use
switchcases instead of an object - Separate the dynamic section component into 2 parts:
client-registryandserver-registry, where the client-registry usesdynamic(() => import())and the server-registry uses only() => import() - Importing all the components directly at the top of the file and just returning them in a switch case, something like:
import SectionA from '@/components/section-a'
export const dynamicSections = {
sectionA: SectionA
}
// or:
export const DynamicSections({ type }: { type: string }) => {
switch (type) {
case 'sectionA':
return <SectionA />;
}
}
There is a Reddit thread that I think is related to this topic: Problem with app router no-one is talking about - Dynamic Loading
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction repository and run its npm install, npm run dev, and npm run build/npm run start flows. Compare the CSS loaded on the products/1 and blog/1 pages, then inspect app/products/[id]/page.tsx and app/blog/[slug]/page.tsx at the referenced imports. Done means confirming the behavior and identifying whether unused component CSS is included in development and production builds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, nextjs, react, tailwindcss, typescript
- Domain
- build-system, frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100