vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.9k stars 26.98k forks source link

RSC checks (build, lint) do not check hooks in child directories #59890

Open jakobo opened 10 months ago

jakobo commented 10 months ago

Link to the code that reproduces this issue

https://github.com/jakobo/next-allowed-compile-rsc

To Reproduce

  1. Check out and install dependencies
  2. Run pnpm lint
  3. Run pnpm build
  4. Run pnpm start --port 3000, wait for server start
  5. Visit http://localhost:3000/a

Current vs. Expected behavior

Expected

  1. A lint error is thrown for using browser APIs and hooks without a "use client" directive (/app/[id]/client.tsx)
  2. A build error is thrown for using browser APIs and hooks without a "use client" directive (/app/[id]/client.tsx)
  3. No build should be generated

Actual

  1. No lint errors are thrown
  2. No build errors are thrown (excepting a top level page.tsx)
  3. A build is generated that is 100% guaranteed to generate a runtime error 500

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP Thu Oct 5 21:02:42 UTC 2023
Binaries:
  Node: 18.19.0
  npm: 10.2.3
  Yarn: N/A
  pnpm: 8.11.0
Relevant Packages:
  next: 14.0.5-canary.23
  eslint-config-next: 14.0.4
  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, ESLint (eslint-config-next)

Additional context

This bug seems to have existed since the original next.js release of React Server Components (13.0.0). We uncovered it during an experiment where a server component called in to an image component with the onError property set. While we caught the runtime error, we were surprised that none of the next build or next lint steps caught the error.

It does fail correctly when we remove the "use client" directive from the top level client.tsx file, but it does not provide the same checks for [id]/client.tsx, making it unclear if this is a build or linting concern.

Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Event handlers cannot be passed to Client Component props.
  {src: ..., onError: function, alt: ...}
                      ^^^^^^^^
If you need interactivity, consider converting part of this to a Client Component.
    at /home/jakobo/code/nextjs/allowed-compile-rsc/node_modules/.pnpm/next@14.0.5-canary.23_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:142290
    at Object.toJSON (/home/jakobo/code/nextjs/allowed-compile-rsc/node_modules/.pnpm/next@14.0.5-canary.23_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:143143)
    at stringify (<anonymous>)
    at eR (/home/jakobo/code/nextjs/allowed-compile-rsc/node_modules/.pnpm/next@14.0.5-canary.23_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:131528)
    at eP (/home/jakobo/code/nextjs/allowed-compile-rsc/node_modules/.pnpm/next@14.0.5-canary.23_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:131971)
    at Timeout._onTimeout (/home/jakobo/code/nextjs/allowed-compile-rsc/node_modules/.pnpm/next@14.0.5-canary.23_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:12:128751)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7)
jakobo commented 9 months ago

In case others come across this, a (partial) workaround is the 3rd party plugin eslint-plugin-react-server-components, which can catch some situations where client-side operations are included without the "use client" directive.