From e6f6373f56e5c0581a659904b8bb4b5daa45458f Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sat, 20 Apr 2024 01:14:25 +0200 Subject: [PATCH 1/7] repro --- .../app/client-import-wildcard/client/a.js | 5 +++ .../app/client-import-wildcard/client/b.js | 5 +++ .../app/client-import-wildcard/client/c.js | 5 +++ .../client-import-wildcard/client/index.js | 5 +++ .../app/client-import-wildcard/page.js | 31 +++++++++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js new file mode 100644 index 0000000000000..77bad2d6dca3b --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js @@ -0,0 +1,5 @@ +'use client' + +export function ClientModExportA() { + return 'client:mod-export-a' +} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js new file mode 100644 index 0000000000000..8a3eaf6044f38 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js @@ -0,0 +1,5 @@ +'use client' + +export function ClientModExportB() { + return 'client:mod-export-b' +} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js new file mode 100644 index 0000000000000..ccd5f55aa56f1 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js @@ -0,0 +1,5 @@ +'use client' + +export function ClientModExportC() { + return 'client:mod-export-c' +} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js new file mode 100644 index 0000000000000..73464c1b8d534 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js @@ -0,0 +1,5 @@ +'use client' + +export { ClientModExportA } from './a' +export { ClientModExportB } from './b' +export { ClientModExportC } from './c' diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js new file mode 100644 index 0000000000000..f38118b15e567 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js @@ -0,0 +1,31 @@ +import * as clientMod from './client' +import { ClientModExportC } from './client' + +const map = { + ...clientMod, +} + +export default function Page() { + const list = ['ClientModExportA', 'ClientModExportB', 'ClientModExportC'] + + const A = map[list[0]] + const B = map[list[1]] + const C = map[list[2]] + + return ( +
+

+ +

+

+ +

+

+ +

+

+ +

+
+ ) +} From abf2bdc6488dae57a84eb584cd99029ca7fe3d57 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sat, 20 Apr 2024 01:56:32 +0200 Subject: [PATCH 2/7] fix: mixing wildcard import and named import client components --- .../plugins/flight-client-entry-plugin.ts | 8 +++++++- .../client-wild-card/client-module.js | 13 ++++++++++++ .../client-wild-card/index.js | 7 +++++++ .../app/client-import-wildcard/page.js | 20 +++++++------------ .../index.test.ts | 9 +++++++++ 5 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index 7f6eb572afa5e..2599973a59d35 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -716,8 +716,14 @@ export class FlightClientEntryPlugin { getModuleReferencesInOrder(mod, compilation.moduleGraph).forEach( (connection: any) => { const dependencyIds: string[] = [] - if (connection.dependency?.ids?.length) { + + // `ids` are the identifiers that are imported from the dependency, + // if it's present, it's an array of strings. + if (connection.dependency?.ids) { dependencyIds.push(...connection.dependency.ids) + } else { + // When using import *, the `ids` are not present + dependencyIds.push('*') } filterClientComponents(connection.resolvedModule, dependencyIds) } diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js new file mode 100644 index 0000000000000..be76aedbea2b8 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js @@ -0,0 +1,13 @@ +'use client' + +export function ClientModExportA() { + return 'client:mod-export-a' +} + +export function ClientModExportB() { + return 'client:mod-export-b' +} + +export function ClientModExportC() { + return 'client:mod-export-c' +} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js new file mode 100644 index 0000000000000..3f93e0c381f46 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js @@ -0,0 +1,7 @@ +'use client' + +export { + ClientModExportA, + ClientModExportB, + ClientModExportC, +} from './client-module' diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js index f38118b15e567..0ee6f17334971 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js @@ -1,29 +1,23 @@ import * as clientMod from './client' import { ClientModExportC } from './client' -const map = { - ...clientMod, -} - export default function Page() { - const list = ['ClientModExportA', 'ClientModExportB', 'ClientModExportC'] - - const A = map[list[0]] - const B = map[list[1]] - const C = map[list[2]] + const A = clientMod.ClientModExportA + const B = clientMod.ClientModExportB + const C = clientMod.ClientModExportC return (
-

+

-

+

-

+

-

+

diff --git a/test/production/app-dir/client-components-tree-shaking/index.test.ts b/test/production/app-dir/client-components-tree-shaking/index.test.ts index 6f28cb7ac01e7..6c2ae8c89061b 100644 --- a/test/production/app-dir/client-components-tree-shaking/index.test.ts +++ b/test/production/app-dir/client-components-tree-shaking/index.test.ts @@ -103,5 +103,14 @@ createNextDescribe( expect($('p').text()).toContain('client:mod-export-default') }) + + it('should handle mixing wildcard imports and named imports from client components', async () => { + const $ = await next.render$('/client-import-wildcard') + + expect($('#a').text()).toContain('client:mod-export-a') + expect($('#b').text()).toContain('client:mod-export-b') + expect($('#c').text()).toContain('client:mod-export-c') + expect($('#named-c').text()).toContain('client:mod-export-c') + }) } ) From 2e67d24bdcf7e516f3b349f8ce94599cdb2296e7 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sun, 21 Apr 2024 03:08:26 +0200 Subject: [PATCH 3/7] merge namespace and named imports into * --- .../plugins/flight-client-entry-plugin.ts | 65 +++++++++++++------ .../client-module.js | 0 .../index.js | 0 .../app/client-import-wildcard/client/a.js | 5 -- .../app/client-import-wildcard/client/b.js | 5 -- .../app/client-import-wildcard/client/c.js | 5 -- .../client-import-wildcard/client/index.js | 5 -- .../app/client-import-wildcard/page.js | 14 ++-- .../{client.js => client-relative-dep.js} | 0 .../app/relative-dep/page.js | 2 +- 10 files changed, 54 insertions(+), 47 deletions(-) rename test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/{client-wild-card => client-wildcard}/client-module.js (100%) rename test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/{client-wild-card => client-wildcard}/index.js (100%) delete mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js delete mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js delete mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js delete mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js rename test/production/app-dir/client-components-tree-shaking/app/relative-dep/{client.js => client-relative-dep.js} (100%) diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index 2599973a59d35..cea3d7eff0bcd 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -670,7 +670,8 @@ export class FlightClientEntryPlugin { mod, modRequest, clientComponentImports, - importedIdentifiers + importedIdentifiers, + false ) } return @@ -707,7 +708,8 @@ export class FlightClientEntryPlugin { mod, modRequest, clientComponentImports, - importedIdentifiers + importedIdentifiers, + true ) return @@ -715,17 +717,18 @@ export class FlightClientEntryPlugin { getModuleReferencesInOrder(mod, compilation.moduleGraph).forEach( (connection: any) => { - const dependencyIds: string[] = [] + let dependencyIds: string[] = [] + const depModule = connection.resolvedModule // `ids` are the identifiers that are imported from the dependency, // if it's present, it's an array of strings. if (connection.dependency?.ids) { dependencyIds.push(...connection.dependency.ids) } else { - // When using import *, the `ids` are not present - dependencyIds.push('*') + dependencyIds = ['*'] } - filterClientComponents(connection.resolvedModule, dependencyIds) + + filterClientComponents(depModule, dependencyIds) } ) } @@ -1036,7 +1039,8 @@ function addClientImport( mod: webpack.NormalModule, modRequest: string, clientComponentImports: ClientComponentImports, - importedIdentifiers: string[] + importedIdentifiers: string[], + isFirstImport: boolean ) { const clientEntryType = getModuleBuildInfo(mod).rsc?.clientEntryType const isCjsModule = clientEntryType === 'cjs' @@ -1045,23 +1049,42 @@ function addClientImport( isCjsModule ? 'commonjs' : 'auto' ) - const isAutoModuleSourceType = assumedSourceType === 'auto' - if (isAutoModuleSourceType) { + const clientImportsSet = clientComponentImports[modRequest] + + if ( + importedIdentifiers.length === 1 && + importedIdentifiers[0] === '*' && + isFirstImport + ) { + // do nothing + } else if ( + // If there's no existing collected import path, + // or there's collected import path but with few named imports, + // we should include the whole module. + !isFirstImport && + [...clientImportsSet][0] !== '*' && + importedIdentifiers[0] === '*' + ) { clientComponentImports[modRequest] = new Set(['*']) } else { - // If it's not analyzed as named ESM exports, e.g. if it's mixing `export *` with named exports, - // We'll include all modules since it's not able to do tree-shaking. - for (const name of importedIdentifiers) { - // For cjs module default import, we include the whole module since - const isCjsDefaultImport = isCjsModule && name === 'default' - - // Always include __esModule along with cjs module default export, - // to make sure it work with client module proxy from React. - if (isCjsDefaultImport) { - clientComponentImports[modRequest].add('__esModule') - } + const isAutoModuleSourceType = assumedSourceType === 'auto' + if (isAutoModuleSourceType) { + clientComponentImports[modRequest] = new Set(['*']) + } else { + // If it's not analyzed as named ESM exports, e.g. if it's mixing `export *` with named exports, + // We'll include all modules since it's not able to do tree-shaking. + for (const name of importedIdentifiers) { + // For cjs module default import, we include the whole module since + const isCjsDefaultImport = isCjsModule && name === 'default' + + // Always include __esModule along with cjs module default export, + // to make sure it work with client module proxy from React. + if (isCjsDefaultImport) { + clientComponentImports[modRequest].add('__esModule') + } - clientComponentImports[modRequest].add(name) + clientComponentImports[modRequest].add(name) + } } } } diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/client-module.js similarity index 100% rename from test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/client-module.js rename to test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/client-module.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/index.js similarity index 100% rename from test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wild-card/index.js rename to test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/index.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js deleted file mode 100644 index 77bad2d6dca3b..0000000000000 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/a.js +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -export function ClientModExportA() { - return 'client:mod-export-a' -} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js deleted file mode 100644 index 8a3eaf6044f38..0000000000000 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/b.js +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -export function ClientModExportB() { - return 'client:mod-export-b' -} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js deleted file mode 100644 index ccd5f55aa56f1..0000000000000 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/c.js +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -export function ClientModExportC() { - return 'client:mod-export-c' -} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js deleted file mode 100644 index 73464c1b8d534..0000000000000 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client/index.js +++ /dev/null @@ -1,5 +0,0 @@ -'use client' - -export { ClientModExportA } from './a' -export { ClientModExportB } from './b' -export { ClientModExportC } from './c' diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js index 0ee6f17334971..9d53addb6760a 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js @@ -1,10 +1,14 @@ -import * as clientMod from './client' -import { ClientModExportC } from './client' +import * as clientMod from './client-wildcard' +import { ClientModExportC } from './client-wildcard' + +const map = { + ...clientMod, +} export default function Page() { - const A = clientMod.ClientModExportA - const B = clientMod.ClientModExportB - const C = clientMod.ClientModExportC + const A = map.ClientModExportA + const B = map.ClientModExportB + const C = map.ClientModExportC return (
diff --git a/test/production/app-dir/client-components-tree-shaking/app/relative-dep/client.js b/test/production/app-dir/client-components-tree-shaking/app/relative-dep/client-relative-dep.js similarity index 100% rename from test/production/app-dir/client-components-tree-shaking/app/relative-dep/client.js rename to test/production/app-dir/client-components-tree-shaking/app/relative-dep/client-relative-dep.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/relative-dep/page.js b/test/production/app-dir/client-components-tree-shaking/app/relative-dep/page.js index 98919f402af88..8ff298db4bb56 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/relative-dep/page.js +++ b/test/production/app-dir/client-components-tree-shaking/app/relative-dep/page.js @@ -1,4 +1,4 @@ -import { ImportedComp } from './client' +import { ImportedComp } from './client-relative-dep' export default function Page() { return From a36b73bcaa4fe759c30b1bcf037ef7e58f51fc70 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sun, 21 Apr 2024 03:26:02 +0200 Subject: [PATCH 4/7] refactor --- .../plugins/flight-client-entry-plugin.ts | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index cea3d7eff0bcd..1b3ec00a22cdb 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -1051,21 +1051,12 @@ function addClientImport( const clientImportsSet = clientComponentImports[modRequest] - if ( - importedIdentifiers.length === 1 && - importedIdentifiers[0] === '*' && - isFirstImport - ) { - // do nothing - } else if ( - // If there's no existing collected import path, - // or there's collected import path but with few named imports, + if (importedIdentifiers[0] === '*') { + // If there's collected import path with named import identifiers, // we should include the whole module. - !isFirstImport && - [...clientImportsSet][0] !== '*' && - importedIdentifiers[0] === '*' - ) { - clientComponentImports[modRequest] = new Set(['*']) + if (!isFirstImport && [...clientImportsSet][0] !== '*') { + clientComponentImports[modRequest] = new Set(['*']) + } } else { const isAutoModuleSourceType = assumedSourceType === 'auto' if (isAutoModuleSourceType) { From b965f85460354e1b2fea503518a4c35c479d98ec Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sun, 21 Apr 2024 03:31:04 +0200 Subject: [PATCH 5/7] rename --- .../client-module}/client-module.js | 0 .../client-module}/index.js | 0 .../page.js | 4 ++-- .../app-dir/client-components-tree-shaking/index.test.ts | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename test/production/app-dir/client-components-tree-shaking/app/{client-import-wildcard/client-wildcard => client-import-namespace/client-module}/client-module.js (100%) rename test/production/app-dir/client-components-tree-shaking/app/{client-import-wildcard/client-wildcard => client-import-namespace/client-module}/index.js (100%) rename test/production/app-dir/client-components-tree-shaking/app/{client-import-wildcard => client-import-namespace}/page.js (79%) diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/client-module.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js similarity index 100% rename from test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/client-module.js rename to test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/index.js similarity index 100% rename from test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/client-wildcard/index.js rename to test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/index.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js similarity index 79% rename from test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js rename to test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js index 9d53addb6760a..edb8211ae8aa1 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-wildcard/page.js +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js @@ -1,5 +1,5 @@ -import * as clientMod from './client-wildcard' -import { ClientModExportC } from './client-wildcard' +import * as clientMod from './client-module' +import { ClientModExportC } from './client-module' const map = { ...clientMod, diff --git a/test/production/app-dir/client-components-tree-shaking/index.test.ts b/test/production/app-dir/client-components-tree-shaking/index.test.ts index 6c2ae8c89061b..abef380fc2f8b 100644 --- a/test/production/app-dir/client-components-tree-shaking/index.test.ts +++ b/test/production/app-dir/client-components-tree-shaking/index.test.ts @@ -104,8 +104,8 @@ createNextDescribe( expect($('p').text()).toContain('client:mod-export-default') }) - it('should handle mixing wildcard imports and named imports from client components', async () => { - const $ = await next.render$('/client-import-wildcard') + it('should handle mixing namespace imports and named imports from client components', async () => { + const $ = await next.render$('/client-import-namespace') expect($('#a').text()).toContain('client:mod-export-a') expect($('#b').text()).toContain('client:mod-export-b') From a56105d7980f50129ca513ac248dabbff9c56429 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sun, 21 Apr 2024 11:19:44 +0200 Subject: [PATCH 6/7] add more test --- .../client-module/client-module.js | 6 ++--- .../client-module2/client-module.js | 9 ++++++++ .../client-module2/index.js | 3 +++ .../app/client-import-namespace/page.js | 23 +++++++++++++++---- .../index.test.ts | 13 +++++++---- 5 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/client-module.js create mode 100644 test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/index.js diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js index be76aedbea2b8..392fb67f3ef48 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module/client-module.js @@ -1,13 +1,13 @@ 'use client' export function ClientModExportA() { - return 'client:mod-export-a' + return 'client-mod:export-a' } export function ClientModExportB() { - return 'client:mod-export-b' + return 'client-mod:export-b' } export function ClientModExportC() { - return 'client:mod-export-c' + return 'client-mod:export-c' } diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/client-module.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/client-module.js new file mode 100644 index 0000000000000..09e233e6bbe50 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/client-module.js @@ -0,0 +1,9 @@ +'use client' + +export function ClientMod2ExportA() { + return 'client-mod2:export-a' +} + +export function ClientMod2ExportB() { + return 'client-mod2:export-b' +} diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/index.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/index.js new file mode 100644 index 0000000000000..0576b901009c2 --- /dev/null +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/client-module2/index.js @@ -0,0 +1,3 @@ +'use client' + +export { ClientMod2ExportA, ClientMod2ExportB } from './client-module' diff --git a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js index edb8211ae8aa1..fbf2486aa56d0 100644 --- a/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js +++ b/test/production/app-dir/client-components-tree-shaking/app/client-import-namespace/page.js @@ -1,15 +1,22 @@ import * as clientMod from './client-module' import { ClientModExportC } from './client-module' +import * as clientMod2 from './client-module2' -const map = { +const mod1Map = { ...clientMod, } -export default function Page() { - const A = map.ClientModExportA - const B = map.ClientModExportB - const C = map.ClientModExportC +const mod2Map = { + ...clientMod2, +} + +const A = mod1Map.ClientModExportA +const B = mod1Map.ClientModExportB +const C = mod1Map.ClientModExportC +const A2 = mod2Map.ClientMod2ExportA +const B2 = mod2Map.ClientMod2ExportB +export default function Page() { return (

@@ -24,6 +31,12 @@ export default function Page() {

+

+ +

+

+ +

) } diff --git a/test/production/app-dir/client-components-tree-shaking/index.test.ts b/test/production/app-dir/client-components-tree-shaking/index.test.ts index abef380fc2f8b..4c1af82cbcac2 100644 --- a/test/production/app-dir/client-components-tree-shaking/index.test.ts +++ b/test/production/app-dir/client-components-tree-shaking/index.test.ts @@ -107,10 +107,15 @@ createNextDescribe( it('should handle mixing namespace imports and named imports from client components', async () => { const $ = await next.render$('/client-import-namespace') - expect($('#a').text()).toContain('client:mod-export-a') - expect($('#b').text()).toContain('client:mod-export-b') - expect($('#c').text()).toContain('client:mod-export-c') - expect($('#named-c').text()).toContain('client:mod-export-c') + // mixing namespace imports and named imports + expect($('#a').text()).toContain('client-mod:export-a') + expect($('#b').text()).toContain('client-mod:export-b') + expect($('#c').text()).toContain('client-mod:export-c') + expect($('#named-c').text()).toContain('client-mod:export-c') + + // only named exports + expect($('#a2').text()).toContain('client-mod2:export-a') + expect($('#b2').text()).toContain('client-mod2:export-b') }) } ) From 5fdcc14118a5b52fc2622acbd631ddbba248d84d Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Sun, 21 Apr 2024 12:06:46 +0200 Subject: [PATCH 7/7] explain --- .../next/src/build/webpack/plugins/flight-client-entry-plugin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts index 1b3ec00a22cdb..932c5356c3e04 100644 --- a/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/flight-client-entry-plugin.ts @@ -1053,6 +1053,7 @@ function addClientImport( if (importedIdentifiers[0] === '*') { // If there's collected import path with named import identifiers, + // or there's nothing in collected imports are empty. // we should include the whole module. if (!isFirstImport && [...clientImportsSet][0] !== '*') { clientComponentImports[modRequest] = new Set(['*'])