Skip to content

Commit

Permalink
fix: babel usage with next/image (#61835)
Browse files Browse the repository at this point in the history
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 #61116

Closes NEXT-2410
Closes NEXT-2328

---------

Co-authored-by: Jiachi Liu <inbox@huozhi.im>
  • Loading branch information
styfle and huozhi committed Feb 28, 2024
1 parent 3efc842 commit 7dbf6f8
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 4 deletions.
22 changes: 18 additions & 4 deletions packages/next/src/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)/
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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),
Expand Down
4 changes: 4 additions & 0 deletions test/integration/babel-next-image/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": []
}
12 changes: 12 additions & 0 deletions test/integration/babel-next-image/app/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
}

export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
12 changes: 12 additions & 0 deletions test/integration/babel-next-image/app/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Image from 'next/image'

export default function Home() {
return (
<Image
alt="red square"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=="
width={64}
height={64}
/>
)
}
19 changes: 19 additions & 0 deletions test/integration/babel-next-image/babel-next-image.test.js
Original file line number Diff line number Diff line change
@@ -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)
})
})

1 comment on commit 7dbf6f8

@AkmaludinFitra

This comment was marked as spam.

Please sign in to comment.