From 3fa9cb7bf7da5aafadd8be8479bc283bd91458c1 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Tue, 23 Apr 2024 09:57:49 +0200 Subject: [PATCH] Fix mixed exports in server component with barrel optimization (#64894) ### What * Remove the change added in #64467, but still kept tests. * Add more tests for mixed imports (component and function) from shared component with `optimizePackageImports` ### Why The fix in #64467 was not correct, as mixing `export *` with `"use client"` should error if Next.js detect it properly. When there's mixed exports, that a shared function will become a client reference if the target file inherits the client boundary. The original issue #64467 fixed was actually related to tree-shaking, which is fixed in #64681. Closes NEXT-3197 --- .../src/build/webpack/loaders/next-barrel-loader.ts | 2 -- .../basic/app/mixed-barrel-imports/page.js | 9 +++++++++ .../app-dir/barrel-optimization/basic/index.test.ts | 6 +++++- .../app-dir/barrel-optimization/basic/next.config.js | 2 +- .../basic/node_modules/mixed-lib/button.js | 11 +++++++++++ .../basic/node_modules/mixed-lib/index.js | 1 + .../basic/node_modules/mixed-lib/package.json | 5 +++++ .../basic/node_modules/my-lib/client/index.js | 2 -- 8 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 test/production/app-dir/barrel-optimization/basic/app/mixed-barrel-imports/page.js create mode 100644 test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/button.js create mode 100644 test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/index.js create mode 100644 test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/package.json diff --git a/packages/next/src/build/webpack/loaders/next-barrel-loader.ts b/packages/next/src/build/webpack/loaders/next-barrel-loader.ts index 32f75eaa26a1e..ba4aa6a78343f 100644 --- a/packages/next/src/build/webpack/loaders/next-barrel-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-barrel-loader.ts @@ -225,8 +225,6 @@ async function getBarrelMapping( if (targetMatches) { // Merge the export list exportList = exportList.concat(targetMatches.exportList) - // Inherit the client boundary from the target matched file - isClientEntry = isClientEntry || targetMatches.isClientEntry } }) ) diff --git a/test/production/app-dir/barrel-optimization/basic/app/mixed-barrel-imports/page.js b/test/production/app-dir/barrel-optimization/basic/app/mixed-barrel-imports/page.js new file mode 100644 index 0000000000000..7c7a50de3df4f --- /dev/null +++ b/test/production/app-dir/barrel-optimization/basic/app/mixed-barrel-imports/page.js @@ -0,0 +1,9 @@ +import { buttonStyle, Button } from 'mixed-lib' + +export default function Page() { + return ( +
+
+ ) +} diff --git a/test/production/app-dir/barrel-optimization/basic/index.test.ts b/test/production/app-dir/barrel-optimization/basic/index.test.ts index 87f3a191f0d61..18be447286fb3 100644 --- a/test/production/app-dir/barrel-optimization/basic/index.test.ts +++ b/test/production/app-dir/barrel-optimization/basic/index.test.ts @@ -8,10 +8,14 @@ describe('Skipped in Turbopack', () => { }, ({ next }) => { it('should build successfully', async () => { - // Ensure that MUI is working const $ = await next.render$('/') expect(await $('#client-mod').text()).toContain('client:default') }) + + it('should handle mixed imports from barrel optimized lib correctly', async () => { + const $ = await next.render$('/mixed-barrel-imports') + expect(await $('#component').attr('style')).toContain('color:blue') + }) } ) }) diff --git a/test/production/app-dir/barrel-optimization/basic/next.config.js b/test/production/app-dir/barrel-optimization/basic/next.config.js index d966eb99681dc..a0c5eeaeace23 100644 --- a/test/production/app-dir/barrel-optimization/basic/next.config.js +++ b/test/production/app-dir/barrel-optimization/basic/next.config.js @@ -1,5 +1,5 @@ module.exports = { experimental: { - optimizePackageImports: ['my-lib'], + optimizePackageImports: ['my-lib', 'mixed-lib'], }, } diff --git a/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/button.js b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/button.js new file mode 100644 index 0000000000000..5daf5c647f4ea --- /dev/null +++ b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/button.js @@ -0,0 +1,11 @@ +import React from 'react' + +export function Button(props) { + return React.createElement('button', props, 'button') +} + +export function buttonStyle() { + return { + color: 'blue', + } +} diff --git a/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/index.js b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/index.js new file mode 100644 index 0000000000000..14757e7223300 --- /dev/null +++ b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/index.js @@ -0,0 +1 @@ +export * from './button' diff --git a/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/package.json b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/package.json new file mode 100644 index 0000000000000..0295fce0d3751 --- /dev/null +++ b/test/production/app-dir/barrel-optimization/basic/node_modules/mixed-lib/package.json @@ -0,0 +1,5 @@ +{ + "name": "mixed-lib", + "type": "module", + "exports": "./index.js" +} diff --git a/test/production/app-dir/barrel-optimization/basic/node_modules/my-lib/client/index.js b/test/production/app-dir/barrel-optimization/basic/node_modules/my-lib/client/index.js index 89f3664232476..bc8cfd59bd5d5 100644 --- a/test/production/app-dir/barrel-optimization/basic/node_modules/my-lib/client/index.js +++ b/test/production/app-dir/barrel-optimization/basic/node_modules/my-lib/client/index.js @@ -1,4 +1,2 @@ -'use client' - export { default } from './client-module' export * from './client-module'