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

JS / CSS Code splitting in app dir does not work as described in the docs #61574

Closed
BleddP opened this issue Feb 2, 2024 · 2 comments
Closed
Labels
Lazy Loading Related to Next.js Lazy Loading (e.g., `next/dynamic` or `React.lazy`).

Comments

@BleddP
Copy link

BleddP commented Feb 2, 2024

Link to the code that reproduces this issue

https://github.com/BleddP/app-dir-code-splitting-bug

To Reproduce

  1. Install the reproduction repo with yarn
  2. Run the app with yarn dev (or you can just go straight ahead and yarn build && yarn start

I have created four variations of the same page, they all use the spread operator as we want dynamic params to render a page from let's say a CMS.

  • The components in [...bundled] are imported as import { ServerWrapper, ClientWrapper } from '@bundled-components' as the bundled-components directory has an index.ts file that exports everything from the components library. This helps with a DRY approach, and makes the code generally more readable and maintainable.

  • There is no index.ts file in the components folder to export everything, so the components in [...components] are imported as:

import { ServerWrapper } from '@components/ServerWrapper/ServerWrapper'
import { ClientWrapper } from '@components/ClientWrapper/ClientWrapper'

Then, both pages (...bundled and ...components) import their components through a wrapper.
One variant is wrapped in a server component, which attempts 1 regular import and 1 dynamic import.
The other is wrapped in a client component, which attempts 1 regular import and 1 dynamic import.

The problem here is that the dynamic import only works when components are not exported from index.ts and when they are wrapped in a client wrapper. This is entirely unclear from the current Next.js docs.

Current vs. Expected behavior

According to the next.js docs: https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading

It allows you to defer loading of Client Components and imported libraries, and only include them in the client bundle when they're needed. For example, you might want to defer loading a modal until a user clicks to open it.

This implies that inside a server component, I can use dynamic to lazy load a client component. But as evidenced by my reproduction repo, there is absolutely no code splitting / lazy loading happening when dynamically importing a client component in a server component.

Expected vs current behaviour
Expected: Any component that is imported using the dynamic import, is lazy loaded.
Current: No component (not even client components) are lazy loaded if using dynamic from within a server component

Additionally, the CSS is bundled together into the main page css, if the component is also dynamically imported from within a server component. It only splits the CSS, if the component is exclusively dynamically imported from another client component. This is very confusing, especially because the lazy loading really does not work as described in your docs.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000
Binaries:
  Node: 18.17.0
  npm: 9.6.7
  Yarn: 1.22.19
  pnpm: N/A
Relevant Packages:
  next: 14.1.1-canary.27 // Latest available version is detected (14.1.1-canary.27).
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router, Dynamic imports (next/dynamic)

Which stage(s) are affected? (Select all that apply)

next dev (local), next start (local)

Additional context

No response

@BleddP BleddP added the bug Issue was opened via the bug report template. label Feb 2, 2024
@github-actions github-actions bot added the Lazy Loading Related to Next.js Lazy Loading (e.g., `next/dynamic` or `React.lazy`). label Feb 2, 2024
@wesnolte
Copy link

wesnolte commented Mar 1, 2024

Thanks for writing this up. I have the same issue. My first load JS on some routes is huge because of it.

@bluebeel
Copy link

I can confirm the next/dynamic doesn't work.
The solution we did for now was using React.lazy where we could. But yeah quite the regression compared to Pages Router ^^'

@samcx samcx removed the bug Issue was opened via the bug report template. label Feb 24, 2025
@samcx samcx closed this as completed Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Lazy Loading Related to Next.js Lazy Loading (e.g., `next/dynamic` or `React.lazy`).
Projects
None yet
Development

No branches or pull requests

4 participants