From b942a6f49448fec65fbdef24142c7bb2c926ace3 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Sat, 25 Feb 2023 00:23:32 -0500 Subject: [PATCH] chore: improve error when exporting metadata from client component (#46334) This improves the ambiguous error seen when exporting `metadata` or `generateMetadata` from a component marked with the `"use client";` directive. Example output from tests (`pnpm test-dev test/development/acceptance-app/rsc-build-errors.test`) ```console File path: app/client-with-errors/metadata-export/page.js console.log browser log: ./app/client-with-errors/metadata-export/page.js ReactServerComponentsError: You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://beta.nextjs.org/docs/api-reference/metadata ,-[6:1] 6 | 7 | // export const metadata = { title: 'client-metadata' } 8 | 9 | export async function generateMetadata() { return { title: 'client-metadata' } } : ^^^^^^^^^^^^^^^^ `---- File path: app/client-with-errors/metadata-export/page.js ``` ## Bug - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) ## Documentation / Examples - [x] Make sure the linting passes by running `pnpm build && pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) --------- Co-authored-by: Jiachi Liu --- .../next-swc/crates/core/src/react_server_components.rs | 7 +++++-- .../webpack/plugins/wellknown-errors-plugin/parseRSC.ts | 9 +++++++++ test/development/acceptance-app/rsc-build-errors.test.ts | 4 ++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/next-swc/crates/core/src/react_server_components.rs b/packages/next-swc/crates/core/src/react_server_components.rs index c77999cf93..8adecb9ea3 100644 --- a/packages/next-swc/crates/core/src/react_server_components.rs +++ b/packages/next-swc/crates/core/src/react_server_components.rs @@ -470,8 +470,11 @@ impl ReactServerComponents { handler .struct_span_err( span, - format!("NEXT_RSC_ERR_INVALID_API: {}", invalid_export_name) - .as_str(), + format!( + "NEXT_RSC_ERR_CLIENT_METADATA_EXPORT: {}", + invalid_export_name + ) + .as_str(), ) .emit() }) diff --git a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseRSC.ts b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseRSC.ts index e89971d689..8b2c52e85c 100644 --- a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseRSC.ts +++ b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseRSC.ts @@ -16,6 +16,8 @@ function formatRSCErrorMessage( const NEXT_RSC_ERR_REACT_API = /.+NEXT_RSC_ERR_REACT_API: (.*?)\n/s const NEXT_RSC_ERR_SERVER_IMPORT = /.+NEXT_RSC_ERR_SERVER_IMPORT: (.*?)\n/s const NEXT_RSC_ERR_CLIENT_IMPORT = /.+NEXT_RSC_ERR_CLIENT_IMPORT: (.*?)\n/s + const NEXT_RSC_ERR_CLIENT_METADATA_EXPORT = + /.+NEXT_RSC_ERR_CLIENT_METADATA_EXPORT: (.*?)\n/s const NEXT_RSC_ERR_CLIENT_DIRECTIVE = /.+NEXT_RSC_ERR_CLIENT_DIRECTIVE\n/s const NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN = /.+NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN\n/s @@ -93,6 +95,13 @@ function formatRSCErrorMessage( `\n\n${fileName} must be a Client Component. Add the "use client" directive the top of the file to resolve this issue.\n\n` ) formattedVerboseMessage = '\n\nImport path:\n' + } else if (NEXT_RSC_ERR_CLIENT_METADATA_EXPORT.test(message)) { + formattedMessage = message.replace( + NEXT_RSC_ERR_CLIENT_METADATA_EXPORT, + `\n\nYou are attempting to export "$1" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://beta.nextjs.org/docs/api-reference/metadata\n\n` + ) + + formattedVerboseMessage = '\n\nFile path:\n' } return [formattedMessage, formattedVerboseMessage] diff --git a/test/development/acceptance-app/rsc-build-errors.test.ts b/test/development/acceptance-app/rsc-build-errors.test.ts index cefca0802e..affd3e3ac6 100644 --- a/test/development/acceptance-app/rsc-build-errors.test.ts +++ b/test/development/acceptance-app/rsc-build-errors.test.ts @@ -55,7 +55,7 @@ createNextDescribe( await session.patch(pageFile, uncomment) expect(await session.hasRedbox(true)).toBe(true) expect(await session.getRedboxSource()).toInclude( - '"metadata" is not supported in app/' + 'You are attempting to export "metadata" from a component marked with "use client", which is disallowed.' ) // Restore file @@ -70,7 +70,7 @@ createNextDescribe( await session.patch(pageFile, uncomment) expect(await session.hasRedbox(true)).toBe(true) expect(await session.getRedboxSource()).toInclude( - '"generateMetadata" is not supported in app/' + 'You are attempting to export "generateMetadata" from a component marked with "use client", which is disallowed.' ) await cleanup()