Stylesheet needed by next/dynamic component removed during client-side navigation via next/link #61111
Labels
bug
Issue was opened via the bug report template.
Lazy Loading
Related to Next.js Lazy Loading (e.g., `next/dynamic` or `React.lazy`).
linear: next
Confirmed issue that is tracked by the Next.js team.
locked
Navigation
Related to Next.js linking (e.g., <Link>) and navigation.
Link to the code that reproduces this issue
https://github.com/copperwall/mini-css-nextjs-repro
To Reproduce
http://localhost:3000
, observe that the element with "Some text" has styling including background-color and a border.http://localhost:3000/client_side_navigation
using client-side navigation vianext/link
.next/dynamic
call, so in this case we'd expect to see the same background-color and border styles as the index page.http://localhost:3000/client_side_navigation
you can observe the style it should haveCurrent vs. Expected behavior
Following the steps from the previous section, I'd expect the
/client_side_navigation
page to have the same style applied as the/
page, since they use the same component and share the same stylesheet.However, the
StyledBoxLazy
on the/client_side_navigation
page is unstyled when the user does a client-side navigation from/
to/client_side_navigation
.Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:55:06 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6020 Binaries: Node: 18.19.0 npm: 10.2.3 Yarn: 1.22.21 pnpm: 8.14.2 Relevant Packages: next: 14.1.1-canary.9 // Latest available version is detected (14.1.1-canary.9). 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)
Dynamic imports (next/dynamic), Routing (next/router, next/navigation, next/link)
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local), next start (local), Other (Deployed)
Additional context
We're running Next via Docker (outside Vercel) but we've been able to reproduce this both in prod and locally. Happy to answer any questions or investigate possible workarounds! From the repro repo I added what seems to be happening and some potential ways to fix it, but I'll include them here too
Explanation
The index page includes a component called
StyledBox
, which has a dependency on a CSS Module. The client-side-navigation page has a dependency onStyledBoxLazy
, which isStyledBox
wrapped withinnext/dyanmic
.The stylesheet is initially included when loading the server-side rendered version of the index page. Because the StyledBox component is not using
next/dyanmic
on the index page, the stylesheet link tag has adata-n-p
attribute.When the user navigates to client-side-navigation via clicking the
Link
component, the client-side-navigation page rendersStyledBoxLazy
, which attempts to load the CSS chunk associated withStyledBoxLazy
. In the webpack runtime chunk,mini-css-extract-plugin
looks up the file path via the chunk/module id and first checks to see if there is alink
tag with arel=stylesheet
and anhref
that matches the filepath for the stylesheet it needs to load. In this case it finds the stylesheet that was loaded via SSR on the initial index pageload, and does not add an additional link tag for that stylesheet (because one already exists in the document). This happens in this section of the plugin https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/src/index.js#L924.After the render phase for client-side-navigation finishes, the
onHeadCommit
method runs in auseLayoutEffect
which cleans up all elements that match thelink[data-n-p]
selector herenext.js/packages/next/src/client/index.tsx
Line 760 in 9de7705
mini-css-extract
had just assumed was going to be in the document, which results in the component that uses that stylesheet to be unstyled when the client-side navigation completes.Possible Fixes
mini-css-extract-plugin
could be patched to not look forlink
tags with thedata-n-p
tag. This means thatmini-css-extract-plugin
would include anotherlink
tag, which would not be cleaned up viaonHeadCommit
when client-side navigation completes.mini-css-extract-plugin
could be patched to remove thedata-n-p
tag for any stylesheets that it looks up, which would stop the stylesheet from being removed byonHeadCommit
when client-side navigation completes.NEXT-2849
The text was updated successfully, but these errors were encountered: