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

Stylesheet needed by next/dynamic component removed during client-side navigation via next/link #61111

Closed
copperwall opened this issue Jan 24, 2024 · 1 comment · Fixed by #64294
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.

Comments

@copperwall
Copy link

copperwall commented Jan 24, 2024

Link to the code that reproduces this issue

https://github.com/copperwall/mini-css-nextjs-repro

To Reproduce

  1. Start the application in production mode
  2. Navigate to http://localhost:3000, observe that the element with "Some text" has styling including background-color and a border.
image
  1. Click on the "To other page" link below to navigate to http://localhost:3000/client_side_navigation using client-side navigation via next/link.
  2. Observe that the element with "Some text" no longer has any styling associated with it. This component is rendered using the same component from the index page, except wrapped in a next/dynamic call, so in this case we'd expect to see the same background-color and border styles as the index page.
image
  1. If you reload http://localhost:3000/client_side_navigation you can observe the style it should have
image

Current 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 on StyledBoxLazy, which is StyledBox wrapped within next/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 a data-n-p attribute.

When the user navigates to client-side-navigation via clicking the Link component, the client-side-navigation page renders StyledBoxLazy, which attempts to load the CSS chunk associated with StyledBoxLazy. 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 a link tag with a rel=stylesheet and an href 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 a useLayoutEffect which cleans up all elements that match the link[data-n-p] selector here

// Finally, clean up server rendered stylesheets:
. This removes the stylesheet element that 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

  1. mini-css-extract-plugin could be patched to not look for link tags with the data-n-p tag. This means that mini-css-extract-plugin would include another link tag, which would not be cleaned up via onHeadCommit when client-side navigation completes.
  2. mini-css-extract-plugin could be patched to remove the data-n-p tag for any stylesheets that it looks up, which would stop the stylesheet from being removed by onHeadCommit when client-side navigation completes.

NEXT-2849

@copperwall copperwall added the bug Issue was opened via the bug report template. label Jan 24, 2024
@github-actions github-actions bot added Lazy Loading Related to Next.js Lazy Loading (e.g., `next/dynamic` or `React.lazy`). Navigation Related to Next.js linking (e.g., <Link>) and navigation. labels Jan 24, 2024
@huozhi huozhi added the linear: next Confirmed issue that is tracked by the Next.js team. label Mar 18, 2024
@huozhi huozhi closed this as completed in 142050d Apr 10, 2024
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants