From 7dbf6f8298daea8e8c5198e9a4e7e758da665a6d Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 8 Feb 2024 18:16:30 -0500 Subject: [PATCH] fix: babel usage with next/image (#61835) The `process/browser` lib was imported and being transformed, but `process.browser = true` turns to `true = true` that causes the compilation error, we need to exclude them from certain compilation layers - Fixes https://github.com/vercel/next.js/issues/61116 Closes NEXT-2410 Closes NEXT-2328 --------- Co-authored-by: Jiachi Liu --- packages/next/src/build/webpack-config.ts | 22 +++++++++++++++---- test/integration/babel-next-image/.babelrc | 4 ++++ .../babel-next-image/app/layout.js | 12 ++++++++++ test/integration/babel-next-image/app/page.js | 12 ++++++++++ .../babel-next-image/babel-next-image.test.js | 19 ++++++++++++++++ 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/integration/babel-next-image/.babelrc create mode 100644 test/integration/babel-next-image/app/layout.js create mode 100644 test/integration/babel-next-image/app/page.js create mode 100644 test/integration/babel-next-image/babel-next-image.test.js diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 497258afa0af4..4c0b906cc50cb 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -110,8 +110,16 @@ const babelIncludeRegexes: RegExp[] = [ /[\\/](strip-ansi|ansi-regex|styled-jsx)[\\/]/, ] -const preCompileReactRegex = - /next[\\/]dist[\\/]compiled[\\/](react|react-dom|react-server-dom-webpack)(-experimental)?($|[\\/])/ +const browserNonTranspileModules = [ + // Transpiling `process/browser` will trigger babel compilation error due to value replacement. + // TypeError: Property left of AssignmentExpression expected node to be of a type ["LVal"] but instead got "BooleanLiteral" + // e.g. `process.browser = true` will become `true = true`. + /[\\/]node_modules[\\/]process[\\/]browser/, + // Exclude precompiled react packages from browser compilation due to SWC helper insertion (#61791), + // We fixed the issue but it's safer to exclude them from compilation since they don't need to be re-compiled. + /[\\/]next[\\/]dist[\\/]compiled[\\/](react|react-dom|react-server-dom-webpack)(-experimental)?($|[\\/])/, +] +const precompileRegex = /[\\/]next[\\/]dist[\\/]compiled[\\/]/ const asyncStoragesRegex = /next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/ @@ -1400,7 +1408,12 @@ export default async function getBaseWebpackConfig( ? [ { test: codeCondition.test, - exclude: [codeCondition.exclude, transpilePackagesRegex], + exclude: [ + // exclude unchanged modules from react-refresh + codeCondition.exclude, + transpilePackagesRegex, + precompileRegex, + ], issuerLayer: WEBPACK_LAYERS.appPagesBrowser, use: reactRefreshLoaders, resolve: { @@ -1443,7 +1456,8 @@ export default async function getBaseWebpackConfig( { test: codeCondition.test, issuerLayer: WEBPACK_LAYERS.appPagesBrowser, - exclude: preCompileReactRegex, + // Exclude the transpilation of the app layer due to compilation issues + exclude: browserNonTranspileModules, use: appBrowserLayerLoaders, resolve: { mainFields: getMainField(compilerType, true), diff --git a/test/integration/babel-next-image/.babelrc b/test/integration/babel-next-image/.babelrc new file mode 100644 index 0000000000000..9fcef0394fdf0 --- /dev/null +++ b/test/integration/babel-next-image/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["next/babel"], + "plugins": [] +} diff --git a/test/integration/babel-next-image/app/layout.js b/test/integration/babel-next-image/app/layout.js new file mode 100644 index 0000000000000..8525f5f8c0b2a --- /dev/null +++ b/test/integration/babel-next-image/app/layout.js @@ -0,0 +1,12 @@ +export const metadata = { + title: 'Next.js', + description: 'Generated by Next.js', +} + +export default function RootLayout({ children }) { + return ( + + {children} + + ) +} diff --git a/test/integration/babel-next-image/app/page.js b/test/integration/babel-next-image/app/page.js new file mode 100644 index 0000000000000..4aa4e6613b0f2 --- /dev/null +++ b/test/integration/babel-next-image/app/page.js @@ -0,0 +1,12 @@ +import Image from 'next/image' + +export default function Home() { + return ( + red square + ) +} diff --git a/test/integration/babel-next-image/babel-next-image.test.js b/test/integration/babel-next-image/babel-next-image.test.js new file mode 100644 index 0000000000000..e9afa0e0b0776 --- /dev/null +++ b/test/integration/babel-next-image/babel-next-image.test.js @@ -0,0 +1,19 @@ +/* eslint-env jest */ + +import { fetchViaHTTP, findPort, killApp, launchApp } from 'next-test-utils' +;(process.env.TURBOPACK ? describe.skip : describe)('babel-next-image', () => { + let appPort + let app + + beforeAll(async () => { + appPort = await findPort() + app = await launchApp(__dirname, appPort) + }) + + afterAll(() => killApp(app)) + + it('should work with babel and next/image', async () => { + const res = await fetchViaHTTP(appPort, '/') + expect(res.status).toBe(200) + }) +})