-
Notifications
You must be signed in to change notification settings - Fork 26.3k
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
Server side dynamic imports will not split client modules in multiple chunks #54935
Comments
Duplicate of the - #49454 |
Expected behavior: When server components are imported via next/dynamic, shouldn't the components be split into chunks on the server? At least the CSS? The issue is that the CSS of all components is bundled into a single CSS file. This naturally leads to performance losses in PageSpeed Insights, especially in larger projects. page.js: import dynamic from 'next/dynamic';
const Page1 = dynamic(() => import('@/components/Page1'));
const Page2 = dynamic(() => import('@/components/Page2'));
const Page = ({ params: { pagename: pagenameArr } }) => {
const pagename = pagenameArr?.[0];
if (pagename === 'page1') return <Page1 />;
if (pagename === 'page2') return <Page2 />;
};
export default Page; component Page1: import styles from "./Page1.module.css";
const Page1 = () => {
return <div className={styles.page1}>Page 1</div>;
};
export default Page1; Page1.module.css .page1 {
background-color: #00ffff;
} component Page2: import styles from "./Page2.module.css";
const Page2 = () => {
return <div className={styles.page2}>Page 2</div>;
};
export default Page2; Page2.module.css .page1 {
background-color: #ff00ee;
} When I open Page1 in the browser, a CSS file (efe31bd8f307aac7.css) is loaded that contains styling from both components: .Page2_page2__PYcEf{background-color:#f0e}
.Page1_page1__9tvyj{background-color:#0ff} |
I've been experiencing a similar issue and read the duplicate, but it was closed, and nothing was done about it. It makes it difficult to understand how to code-split in NextJS 14. The claim was that it would be "automatic" and that any client component imported inside a server component that suspends and streams progressively would not increase FirstLoadJS, but I'm finding that this isn't true at all. Instead, all client code is sent to the browser at the same time, regardless of whether it renders initially, unless you code-split inside a client component, which introduces an unnecessary round-trip. Nothing you can do on the server, whether using |
Our biggest problem is not necessarily the splitting of JS files (that works as long as you integrate another component that then loads again via next/dynamic), but rather CSS files that become far too large and cannot be split. It would be sensational if an intelligent solution were sought for this. |
I am experiencing exactly the same problem. Using Next 14 (canary), I have a catch-all route in This means that dedicated client-components (such as form inputs, checkboxes, modals, etc), which are dynamically imported from a client wrapper, still have their CSS bundled into the big CSS files, even though those components are not used on the page at all. Next.js is supposed to be all about performance, but how can you benefit from reduced client-side javascript if you have a huge render-blocking CSS destroying your performance metrics. |
Progress on this topic would be great. I think there must be the option to split CSS files (rendering blocking). We have big losses in Pagespeed Insights because of this. |
So I've done a bit more research on this, and managed to get the CSS and JS code-splitting working, but only when used in very specific circumstances. First and foremost, I have realised that if you have a So the JS file and CSS is lazy loaded, only if the following conditions are met:
In relation to point 3, I've found that if you'd have a server component like this:
Then it just loads the Textinput component, including CSS which will be bundled in the main CSS file. Tbh it's a real pain to have to create these workarounds, but if performance is absolutely paramount for your project then I hope these steps might help someone who's stuck like I was. |
@leerob any update here? Also anything on an option to split CSS files (rendering blocking) |
dynamic only works properly in client components. More info: vercel/next.js#54935 (comment)
Link to the code that reproduces this issue or a replay of the bug
https://github.com/leo-cheron/nextjs-issue-dynamic
To Reproduce
Dynamically multiple server of client components from a server page / component:
Where ServerComponentA & B will import respectively ClientComponentA & ClientComponentB like below:
ClientComponentA being just a large SVG:
Current vs. Expected behavior
According to the documentation, If you dynamically import a Server Component, only the Client Components that are children of the Server Component will be lazy-loaded - not the Server Component itself.
By running bundle analyze, we see that both
ClientComponentA
&ClientComponentB
are added to same page chunk, where we'd expect them to be split in two lazy loaded separated chunks. This issue defeats the purpose of dynamic loading and will prevent any client module from being loaded on demand.I also tried to dynamically import
ClientComponentA
fromServerComponentA
without success. Chunk splitting would only work when dynamic import is used from a client component (which we don't want here).Build prod demo can be found here
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.6.0: Wed Jul 5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 Binaries: Node: 19.8.1 npm: 9.5.1 Yarn: 1.22.17 pnpm: 8.7.0 Relevant Packages: next: 13.4.20-canary.15 eslint-config-next: N/A react: 18.2.0 react-dom: 18.2.0 typescript: 5.2.2 Next.js Config: output: N/A
Which area(s) are affected? (Select all that apply)
App Router
Additional context
Any production build is concerned.
The text was updated successfully, but these errors were encountered: