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

match resource imports are not working in React Server Components (App Router) #53366

Closed
1 task done
jantimon opened this issue Jul 31, 2023 · 1 comment · Fixed by #53796
Closed
1 task done

match resource imports are not working in React Server Components (App Router) #53366

jantimon opened this issue Jul 31, 2023 · 1 comment · Fixed by #53796
Labels
bug Issue was opened via the bug report template. locked

Comments

@jantimon
Copy link
Contributor

jantimon commented Jul 31, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

npx --no-install next info

    Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.16.0
      npm: 9.5.1
      Yarn: 1.22.19
      pnpm: N/A
    Relevant Packages:
      next: 13.4.13-canary.6
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: N/A
    Next.js Config:
      output: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App Router

Link to the code that reproduces this issue or a replay of the bug

https://github.com/jantimon/next-css-import-bug-reproduction

To Reproduce

  1. Open http://localhost:3000/use-client in your browser.
"use client"
import styles from './page.module.css!=!../example.txt'

export default function Home() {
  return <div className={styles.demo}>Demo</div>
}
  1. You will see a red text saying "Demo".
    preview client components
  2. Open http://localhost:3000/rsc in your browser.
import styles from './page.module.css!=!../example.txt'

export default function Home() {
  return <div className={styles.demo}>Demo</div>
}
  1. You will see a text saying "Demo" - however it is black.
    preview rsc
  2. Both texts will have the very same css class names.

Describe the Bug

Our css-in-js solution extracts css statically and therefore needs to add css from react (.tsx,...) files.

Unfortunately I encountered a bug in Next.js (version 13.4.13-canary.6 but probably all previous versions behave similar) when using React Server Components (RSC). It appears that the new App Router does not fully support the !=! pattern for overwriting the resource name in the request string.

The compilation works and the correct css modules class name is used.
However the css is not linked to the page.

Adding use client will fix the issue but disable server components.

Expected Behavior

Overwriting the resource name should work for React Server Components (RSC) the same way it does for client components.

Findings

The reason seems to be an invalid mapping inside .next/server/app/page_client-reference-manifest.js.
The ssrModuleMapping from addSSRIDMapping in

points to a css module.

Therefore the linked css module is rendered by react-server-dom-webpack and unfortunately the default export of the css module is not a valid react component.

=> the SSR/SSG fails with the error Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.

Update:

The reason for the wrong mapping is the path handling inside flight-client-entry-plugin.ts:

const modResource = mod.resourceResolveData?.path || mod.resource

mod.resource includes the querystring
but
mod.resourceResolveData.path does not include the query string:

 resource: '/my-next-app/app/Fancy.tsx?./Fancy',
 resourceResolveData: {
    path: '/my-next-app/app/Kaput.tsx',
    query: '?./Fancy', 
    ....
}

Possible solutions:

Use the querystring also in cases where mod.resourceResolveData is available:

const modResource = mod.resourceResolveData 
  ? mod.resourceResolveData.path + mod.resourceResolveData.query
  : mod.resource

Or another possible solution would be to also use mod.matchResource:

const modResource = mod.matchResource || (mod.resourceResolveData 
  ? mod.resourceResolveData.path + mod.resourceResolveData.query
  : mod.resource)
@jantimon jantimon added the bug Issue was opened via the bug report template. label Jul 31, 2023
@jantimon jantimon changed the title special imports are not working in React Server Components (App Router) match resource imports are not working in React Server Components (App Router) Jul 31, 2023
@kodiakhq kodiakhq bot closed this as completed in #53796 Aug 11, 2023
kodiakhq bot pushed a commit that referenced this issue Aug 11, 2023
### Bug Fix
fixes #53366



### Change

Add `query` and [`matchResource`](https://webpack.js.org/api/loaders/#inline-matchresource) to the module mapping. 



### Why

`mod.resource` and all other paths inside `packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts` are already using the query:

https://github.com/vercel/next.js/blob/e127c51327ee9191098fb7b73c681db934505dcc/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts#L506-L507

https://github.com/vercel/next.js/blob/e127c51327ee9191098fb7b73c681db934505dcc/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts#L584-L585



### Motivation

We are using a static extraction css-in-js solution which uses the [inline match resource feature](https://webpack.js.org/api/loaders/#inline-matchresource) (see more in #53366)

As a css-in-js file contains the TSX and the CSS code we have to split the file into two modules which share the same `resource.path`.  

This works well however there is a problem in the mapping inside `.next/server/app/page_client-reference-manifest.js`.
The `ssrModuleMapping` from `addSSRIDMapping` in 
https://github.com/vercel/next.js/blob/e127c51327ee9191098fb7b73c681db934505dcc/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts#L270 links to the latest module (the css part) and not the the initial one (the js part).

Therefore the css module is rendered [react-server-dom-webpack](https://www.npmjs.com/package/react-server-dom-webpack/v/0.0.1?activeTab=versions) and breaks.

The SSR/SSG fails with the error `Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.`

Co-authored-by: Shu Ding <3676859+shuding@users.noreply.github.com>
@github-actions
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 Aug 26, 2023
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. locked
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant