vercel / vercel/next.js

Dynamic import of SSR components is causing the CSS of all components to be loaded

Open
#86,777 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

CSS
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

  1. Clone the project
  2. Run npm install
  3. Start the dev server with: npm run dev

With production build

  1. Clone the project
  2. Run npm install
  3. Build the app: npm run build
  4. 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:

Image

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:

Image

Now, if you open the http://localhost:3000/blog/1 you will see 2 files as well.

Image

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):

Image

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:

Image Image

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 switch cases instead of an object
  • Separate the dynamic section component into 2 parts: client-registry and server-registry, where the client-registry uses dynamic(() => 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.