From 56d0988af729850185bcd186269497e9de5f3f02 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 12 Apr 2024 10:52:40 +0200 Subject: [PATCH] Fix: css in next/dynamic component in edge runtime (#64382) ### What Wrap async local storage for all edge runtime routes in adapter Basically fixed the case reported in [this tweet](https://x.com/keegandonley/status/1778538456458854880) ### Why We're relying on the ALS for dynamic css preloading but we didn't wrap the ALS for request handlers for edge. So if you have CSS imports in `next/dynamic` in edge runtime it would break. Closes NEXT-3085 --- packages/next/src/server/web/adapter.ts | 8 +++++++- .../src/shared/lib/lazy-dynamic/preload-css.tsx | 8 ++++---- .../app-dir/dynamic-css/app/ssr/edge/page.js | 3 +++ test/e2e/app-dir/dynamic-css/index.test.ts | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/e2e/app-dir/dynamic-css/app/ssr/edge/page.js diff --git a/packages/next/src/server/web/adapter.ts b/packages/next/src/server/web/adapter.ts index 1a54ae7c5f6496..cd7fef6999f8f9 100644 --- a/packages/next/src/server/web/adapter.ts +++ b/packages/next/src/server/web/adapter.ts @@ -244,7 +244,13 @@ export async function adapter( ) ) } - return params.handler(request, event) + return RequestAsyncStorageWrapper.wrap( + requestAsyncStorage, + { + req: request, + }, + () => params.handler(request, event) + ) }) // check if response is a Response object diff --git a/packages/next/src/shared/lib/lazy-dynamic/preload-css.tsx b/packages/next/src/shared/lib/lazy-dynamic/preload-css.tsx index cc1549e970cc07..bba8b8c7db2213 100644 --- a/packages/next/src/shared/lib/lazy-dynamic/preload-css.tsx +++ b/packages/next/src/shared/lib/lazy-dynamic/preload-css.tsx @@ -5,10 +5,10 @@ export function PreloadCss({ moduleIds }: { moduleIds: string[] | undefined }) { if (typeof window !== 'undefined') { return null } - const { - getExpectedRequestStore, - } = require('../../../client/components/request-async-storage.external') - const requestStore = getExpectedRequestStore() + const getExpectedRequestStore: typeof import('../../../client/components/request-async-storage.external').getExpectedRequestStore = + require('../../../client/components/request-async-storage.external').getExpectedRequestStore + + const requestStore = getExpectedRequestStore('next/dynamic css') const allFiles = [] diff --git a/test/e2e/app-dir/dynamic-css/app/ssr/edge/page.js b/test/e2e/app-dir/dynamic-css/app/ssr/edge/page.js new file mode 100644 index 00000000000000..943a37c4b42308 --- /dev/null +++ b/test/e2e/app-dir/dynamic-css/app/ssr/edge/page.js @@ -0,0 +1,3 @@ +export { default } from '../page' + +export const runtime = 'edge' diff --git a/test/e2e/app-dir/dynamic-css/index.test.ts b/test/e2e/app-dir/dynamic-css/index.test.ts index 2892e69fbc4666..fb4e867c240728 100644 --- a/test/e2e/app-dir/dynamic-css/index.test.ts +++ b/test/e2e/app-dir/dynamic-css/index.test.ts @@ -31,6 +31,23 @@ createNextDescribe( }) }) + it('should only apply corresponding css for page loaded in edge runtime', async () => { + const browser = await next.browser('/ssr/edge') + await retry(async () => { + expect( + await browser.eval( + `window.getComputedStyle(document.querySelector('.text')).color` + ) + ).toBe('rgb(255, 0, 0)') + // Default border width, which is not effected by bar.css that is not loaded in /ssr + expect( + await browser.eval( + `window.getComputedStyle(document.querySelector('.text')).borderWidth` + ) + ).toBe('0px') + }) + }) + it('should only apply corresponding css for page loaded that /another', async () => { const browser = await next.browser('/another') await retry(async () => {