From 3e341678cbfed6eb81e883cfa0c209ed712be06a Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Wed, 25 Oct 2023 23:38:35 -0700 Subject: [PATCH] Fix missing SWC transforms for optimized barrel files (#57474) With Barrel Optimization, we are trying to "shortcut" the import to be directly pointing to the final target, as barrel files shouldn't have any side effects. However, there could be `"use client"` and `"use server"` directives which we can't ignore. Hence we must apply the `serverComponents` transform of SWC to these barrel files too. Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../next/src/build/webpack/loaders/next-barrel-loader.ts | 6 ++++++ test/development/basic/barrel-optimization.test.ts | 5 +++++ .../basic/barrel-optimization/app/client-boundary/page.js | 5 +++++ test/development/basic/barrel-optimization/next.config.js | 3 ++- .../node_modules_bak/my-client-lib/button.js | 6 ++++++ .../node_modules_bak/my-client-lib/index.js | 3 +++ 6 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/development/basic/barrel-optimization/app/client-boundary/page.js create mode 100644 test/development/basic/barrel-optimization/node_modules_bak/my-client-lib/button.js create mode 100644 test/development/basic/barrel-optimization/node_modules_bak/my-client-lib/index.js 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 49defba08c1bf..18bc3162ce5b5 100644 --- a/packages/next/src/build/webpack/loaders/next-barrel-loader.ts +++ b/packages/next/src/build/webpack/loaders/next-barrel-loader.ts @@ -88,6 +88,7 @@ import type webpack from 'webpack' import path from 'path' import { transform } from '../../swc' +import { WEBPACK_LAYERS } from '../../../lib/constants' // This is a in-memory cache for the mapping of barrel exports. This only applies // to the packages that we optimize. It will never change (e.g. upgrading packages) @@ -103,6 +104,7 @@ const barrelTransformMappingCache = new Map< >() async function getBarrelMapping( + layer: string | null | undefined, resourcePath: string, swcCacheDir: string, resolve: (context: string, request: string) => Promise, @@ -133,6 +135,9 @@ async function getBarrelMapping( optimizeBarrelExports: { wildcard: isWildcard, }, + serverComponents: { + isReactServerLayer: layer === WEBPACK_LAYERS.reactServerComponents, + }, jsc: { parser: { syntax: isTypeScript ? 'typescript' : 'ecmascript', @@ -244,6 +249,7 @@ const NextBarrelLoader = async function ( }) const mapping = await getBarrelMapping( + this._module?.layer, this.resourcePath, swcCacheDir, resolve, diff --git a/test/development/basic/barrel-optimization.test.ts b/test/development/basic/barrel-optimization.test.ts index 7523cac2c65d7..c98e7dbcd8c8b 100644 --- a/test/development/basic/barrel-optimization.test.ts +++ b/test/development/basic/barrel-optimization.test.ts @@ -148,4 +148,9 @@ describe('optimizePackageImports', () => { const html = await next.render('/client') expect(html).toContain('this is a client component') }) + + it('should support "use client" directive in barrel file', async () => { + const html = await next.render('/client-boundary') + expect(html).toContain('') + }) }) diff --git a/test/development/basic/barrel-optimization/app/client-boundary/page.js b/test/development/basic/barrel-optimization/app/client-boundary/page.js new file mode 100644 index 0000000000000..352cbe200b25f --- /dev/null +++ b/test/development/basic/barrel-optimization/app/client-boundary/page.js @@ -0,0 +1,5 @@ +import { Button } from 'my-client-lib' + +export default function Page() { + return +} diff --git a/test/development/basic/barrel-optimization/node_modules_bak/my-client-lib/index.js b/test/development/basic/barrel-optimization/node_modules_bak/my-client-lib/index.js new file mode 100644 index 0000000000000..f8e52095e1bd2 --- /dev/null +++ b/test/development/basic/barrel-optimization/node_modules_bak/my-client-lib/index.js @@ -0,0 +1,3 @@ +'use client' + +export { Button } from './button'