From 5a5396eacd1553afd7a1fd600bd2ac3f67e35522 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 28 May 2024 18:31:03 +0200 Subject: [PATCH 1/8] Fix esm property def in flight loader --- .../build/webpack/loaders/next-flight-loader/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index 79a0ae48ef6ea..01804c6d07857 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -97,20 +97,26 @@ export default function transformSource( return } + // `proxy` is the module proxy that we treat the module as a client boundary. + // For ESM, we access the property of the module proxy directly for each export. + // This is bit hacky that treating using a CJS like module proxy for ESM's exports, + // but this will avoid creating nested proxies for each export. It will be improved in the future. let esmSource = `\ import { createProxy } from "${MODULE_PROXY_PATH}" + +const proxy = createProxy(String.raw\`${this.resourcePath}\`) ` let cnt = 0 for (const ref of clientRefs) { if (ref === '') { - esmSource += `\nexports[''] = createProxy(String.raw\`${resourceKey}#\`);` + esmSource += `\nexports[''] = proxy[''];` } else if (ref === 'default') { esmSource += `\ export default createProxy(String.raw\`${resourceKey}#default\`); ` } else { esmSource += ` -const e${cnt} = createProxy(String.raw\`${resourceKey}#${ref}\`); +const e${cnt} = proxy["${ref}"]; export { e${cnt++} as ${ref} };` } } From a3aafc650772ebbde3f0f543968e997f20726430 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 29 May 2024 21:14:17 +0200 Subject: [PATCH 2/8] update test --- .../app-routes-client-component.test.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/test/e2e/app-dir/app-routes-client-component/app-routes-client-component.test.ts b/test/e2e/app-dir/app-routes-client-component/app-routes-client-component.test.ts index 94c1c8f1c7707..b0a5079ac0a64 100644 --- a/test/e2e/app-dir/app-routes-client-component/app-routes-client-component.test.ts +++ b/test/e2e/app-dir/app-routes-client-component/app-routes-client-component.test.ts @@ -1,20 +1,14 @@ -import { FileRef, nextTestSetup } from 'e2e-utils' -import path from 'path' +import { nextTestSetup } from 'e2e-utils' describe('referencing a client component in an app route', () => { const { next } = nextTestSetup({ - files: new FileRef(path.join(__dirname)), - dependencies: { - react: '19.0.0-rc-f994737d14-20240522', - 'react-dom': '19.0.0-rc-f994737d14-20240522', - }, + files: __dirname, }) it('responds without error', async () => { expect(JSON.parse(await next.render('/runtime'))).toEqual({ - // Turbopack's proxy components are functions - clientComponent: process.env.TURBOPACK ? 'function' : 'object', - myModuleClientComponent: process.env.TURBOPACK ? 'function' : 'object', + clientComponent: 'function', + myModuleClientComponent: 'function', }) }) }) From ff4bbf878acde7eed70c3e881c566e8889aa511b Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 29 May 2024 22:01:42 +0200 Subject: [PATCH 3/8] fix barrel optmization case --- .../webpack/loaders/next-flight-loader/index.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index 01804c6d07857..b373b7fc443f6 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -104,20 +104,17 @@ export default function transformSource( let esmSource = `\ import { createProxy } from "${MODULE_PROXY_PATH}" -const proxy = createProxy(String.raw\`${this.resourcePath}\`) +const proxy = createProxy(String.raw\`${resourceKey}\`) ` let cnt = 0 for (const ref of clientRefs) { if (ref === '') { - esmSource += `\nexports[''] = proxy[''];` + esmSource += `exports[''] = proxy['']\n` } else if (ref === 'default') { - esmSource += `\ -export default createProxy(String.raw\`${resourceKey}#default\`); -` + esmSource += `export default createProxy(String.raw\`${resourceKey}#default\`)\n` } else { - esmSource += ` -const e${cnt} = proxy["${ref}"]; -export { e${cnt++} as ${ref} };` + esmSource += `const e${cnt} = proxy["${ref}"];\n` + esmSource += `export { e${cnt++} as ${ref} };\n` } } From 37906de4a9a6125ed160fe8d000a12feb222566a Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Mon, 3 Jun 2024 20:30:15 +0200 Subject: [PATCH 4/8] update tests case --- packages/next/src/shared/lib/lazy-dynamic/loadable.tsx | 2 +- test/e2e/app-dir/dynamic/app/dynamic/named-export/page.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx b/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx index 31b6e459e93d8..5950b1d82ce2f 100644 --- a/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx +++ b/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx @@ -15,7 +15,7 @@ function convertModule

( // Cases: // mod: { default: Component } // mod: Component - // mod: { $$typeof, default: proxy(Component) } + // mod: { default: proxy(Component) } // mod: proxy(Component) const hasDefault = mod && 'default' in mod return { diff --git a/test/e2e/app-dir/dynamic/app/dynamic/named-export/page.js b/test/e2e/app-dir/dynamic/app/dynamic/named-export/page.js index b767273ab6077..3285b72c5f559 100644 --- a/test/e2e/app-dir/dynamic/app/dynamic/named-export/page.js +++ b/test/e2e/app-dir/dynamic/app/dynamic/named-export/page.js @@ -2,7 +2,7 @@ import dynamic from 'next/dynamic' const Button = dynamic(() => import('./client').then((mod) => { - return mod.Button + return { default: mod.Button } }) ) From 1b3cbe99820fbf85a73d2684155264ee366e4e30 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 4 Jun 2024 10:52:34 +0200 Subject: [PATCH 5/8] update default --- .../next/src/build/webpack/loaders/next-flight-loader/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index b373b7fc443f6..a67a48f1e0b7f 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -111,7 +111,7 @@ const proxy = createProxy(String.raw\`${resourceKey}\`) if (ref === '') { esmSource += `exports[''] = proxy['']\n` } else if (ref === 'default') { - esmSource += `export default createProxy(String.raw\`${resourceKey}#default\`)\n` + esmSource += `export default proxy.default\n` } else { esmSource += `const e${cnt} = proxy["${ref}"];\n` esmSource += `export { e${cnt++} as ${ref} };\n` From 4c455fb025ea1702868babd54c5b8014abbbd1ee Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 4 Jun 2024 13:50:23 +0200 Subject: [PATCH 6/8] revert --- .../next/src/build/webpack/loaders/next-flight-loader/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index a67a48f1e0b7f..b373b7fc443f6 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -111,7 +111,7 @@ const proxy = createProxy(String.raw\`${resourceKey}\`) if (ref === '') { esmSource += `exports[''] = proxy['']\n` } else if (ref === 'default') { - esmSource += `export default proxy.default\n` + esmSource += `export default createProxy(String.raw\`${resourceKey}#default\`)\n` } else { esmSource += `const e${cnt} = proxy["${ref}"];\n` esmSource += `export { e${cnt++} as ${ref} };\n` From 43e8604184fa731eb2d21c9217e2fd6c318c2259 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 4 Jun 2024 13:52:19 +0200 Subject: [PATCH 7/8] remove extra await and use proxy.default --- .../next/src/build/webpack/loaders/next-flight-loader/index.ts | 2 +- packages/next/src/server/app-render/create-component-tree.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index b373b7fc443f6..a67a48f1e0b7f 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -111,7 +111,7 @@ const proxy = createProxy(String.raw\`${resourceKey}\`) if (ref === '') { esmSource += `exports[''] = proxy['']\n` } else if (ref === 'default') { - esmSource += `export default createProxy(String.raw\`${resourceKey}#default\`)\n` + esmSource += `export default proxy.default\n` } else { esmSource += `const e${cnt} = proxy["${ref}"];\n` esmSource += `export { e${cnt++} as ${ref} };\n` diff --git a/packages/next/src/server/app-render/create-component-tree.tsx b/packages/next/src/server/app-render/create-component-tree.tsx index acee5b460119a..e7a076f0baec4 100644 --- a/packages/next/src/server/app-render/create-component-tree.tsx +++ b/packages/next/src/server/app-render/create-component-tree.tsx @@ -265,7 +265,7 @@ async function createComponentTreeInternal({ } const LayoutOrPage: React.ComponentType | undefined = layoutOrPageMod - ? await interopDefault(layoutOrPageMod) + ? interopDefault(layoutOrPageMod) : undefined /** From f3287aa180ca9881fbe73cfe08f4a1c6c869d190 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 4 Jun 2024 14:30:57 +0200 Subject: [PATCH 8/8] revert --- .../next/src/build/webpack/loaders/next-flight-loader/index.ts | 2 +- packages/next/src/server/app-render/create-component-tree.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts index a67a48f1e0b7f..46d6b0ede8142 100644 --- a/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-flight-loader/index.ts @@ -111,7 +111,7 @@ const proxy = createProxy(String.raw\`${resourceKey}\`) if (ref === '') { esmSource += `exports[''] = proxy['']\n` } else if (ref === 'default') { - esmSource += `export default proxy.default\n` + esmSource += `export default createProxy(String.raw\`${resourceKey}#default\`);\n` } else { esmSource += `const e${cnt} = proxy["${ref}"];\n` esmSource += `export { e${cnt++} as ${ref} };\n` diff --git a/packages/next/src/server/app-render/create-component-tree.tsx b/packages/next/src/server/app-render/create-component-tree.tsx index e7a076f0baec4..acee5b460119a 100644 --- a/packages/next/src/server/app-render/create-component-tree.tsx +++ b/packages/next/src/server/app-render/create-component-tree.tsx @@ -265,7 +265,7 @@ async function createComponentTreeInternal({ } const LayoutOrPage: React.ComponentType | undefined = layoutOrPageMod - ? interopDefault(layoutOrPageMod) + ? await interopDefault(layoutOrPageMod) : undefined /**