From c124cabdc7af4f55155543b70b18f73a4d0fa941 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Mon, 24 Oct 2022 17:33:19 -0700 Subject: [PATCH] Fix edge entry layer resolution bug (#41757) By default the edge page entry is in the client layer because it bundles Next.js. It's a virtual loader (edge-ssr-loader) but that makes the SWC loader think the page's source is a client component. We use the resource query `__edge_ssr_entry__` to convert it to the server layer but we need to add that condition to the SWC loader too. ## Bug - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see `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` - [ ] Integration 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` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) --- packages/next/build/webpack-config.ts | 26 ++++++++++++------- .../app-dir/app/app/edge-apis/cookies/page.js | 8 ++++++ test/e2e/app-dir/index.test.ts | 5 ++++ 3 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 test/e2e/app-dir/app/app/edge-apis/cookies/page.js diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index a3bf3cf8169e467..f3e3ada77e391ab 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -729,6 +729,16 @@ export default async function getBaseWebpackConfig( babel: getBabelOrSwcLoader(), } + const swcLoaderForRSC = hasServerComponents + ? useSWCLoader + ? getSwcLoader({ isServerLayer: true }) + : // When using Babel, we will have to add the SWC loader + // as an additional pass to handle RSC correctly. + // This will cause some performance overhead but + // acceptable as Babel will not be recommended. + [getSwcLoader({ isServerLayer: true }), getBabelLoader()] + : [] + const pageExtensions = config.pageExtensions const outputPath = @@ -1789,16 +1799,12 @@ export default async function getBaseWebpackConfig( test: codeCondition.test, issuerLayer: WEBPACK_LAYERS.server, exclude: [staticGenerationAsyncStorageRegex], - use: useSWCLoader - ? getSwcLoader({ isServerLayer: true }) - : // When using Babel, we will have to add the SWC loader - // as an additional pass to handle RSC correctly. - // This will cause some performance overhead but - // acceptable as Babel will not be recommended. - [ - getSwcLoader({ isServerLayer: true }), - getBabelLoader(), - ], + use: swcLoaderForRSC, + }, + { + test: codeCondition.test, + resourceQuery: /__edge_ssr_entry__/, + use: swcLoaderForRSC, }, ] : []), diff --git a/test/e2e/app-dir/app/app/edge-apis/cookies/page.js b/test/e2e/app-dir/app/app/edge-apis/cookies/page.js new file mode 100644 index 000000000000000..15fa568241f754c --- /dev/null +++ b/test/e2e/app-dir/app/app/edge-apis/cookies/page.js @@ -0,0 +1,8 @@ +import { cookies } from 'next/headers' + +export const runtime = 'experimental-edge' + +export default function Page() { + cookies() + return

Hello!

+} diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index b80f8316362bee8..a8740a0d0d10385 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -955,6 +955,11 @@ describe('app dir', () => { } }) + it('should retrieve cookies in a server component in the edge runtime', async () => { + const res = await fetchViaHTTP(next.url, '/edge-apis/cookies') + expect(await res.text()).toInclude('Hello') + }) + it('should access cookies on navigation', async () => { const browser = await webdriver(next.url, '/navigation')