Skip to content

Commit

Permalink
Fix attempted import error for react (#61791)
Browse files Browse the repository at this point in the history
### What

Exclude precompiled react packages from browser layer loaders coverage.

### Why

Since we're transpiling all the browser layer code now after #59569,
then SWC will also compile react. But when it compiles
`react.production.min.js` it gives me with the code and ESM helper
inserted

```js
import { _ as _type_of } from "@swc/helpers/_/_type_of"; // This is not correct
var l = Symbol.for("react.element"), n = Symbol.for("react.portal"), p = Symbol.for("react.fragment"), q = Sym
bol.for("react.strict_mode"), r = Symbol.for("react.profiler"), t = Symbol.for("react.provider"), u = Symbol.f
```

This makes bundler think it's a ESM package but actually it's CJS, which
converts the module into `{ default: .., __esModule }` instead of the
original react module.

When you're using `React.useEffect` or other API through namespace
import (`import * as React from 'react'`), this will break the module
exports check in bundling as the property doesn't directly attached to
the module now. This PR disabled the transform for precompiled react
packages now and will see the deeper issue in next-swc side later.

Fixes #60890
Fixes #61185

Closes NEXT-2362
  • Loading branch information
huozhi authored Feb 7, 2024
1 parent 53fd5ac commit ed3ee38
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/next/src/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ const babelIncludeRegexes: RegExp[] = [
/[\\/](strip-ansi|ansi-regex|styled-jsx)[\\/]/,
]

const preCompileReactRegex =
/next[\\/]dist[\\/]compiled[\\/](react|react-dom|react-server-dom-webpack)(-experimental)?($|[\\/])/

const asyncStoragesRegex =
/next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/

Expand Down Expand Up @@ -1468,6 +1471,7 @@ export default async function getBaseWebpackConfig(
{
test: codeCondition.test,
issuerLayer: WEBPACK_LAYERS.appPagesBrowser,
exclude: preCompileReactRegex,
use: appBrowserLayerLoaders,
resolve: {
mainFields: getMainField(compilerType, true),
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/app-dir/app-external/app-external.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ createNextDescribe(
const v2 = html.match(/External React Version: ([^<]+)</)[1]
expect(v1).toBe(v2)
})

it('should support namespace import with ESM packages', async () => {
const $ = await next.render$('/esm/react-namespace-import')
expect($('#namespace-import-esm').text()).toBe('namespace-import:esm')
})
})

describe('mixed syntax external modules', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use client'

import { NamespaceImport } from 'namespace-import-esm'

export default function Page() {
return (
<>
<NamespaceImport id="namespace-import-esm" />
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as React from 'react'

export function NamespaceImport(props) {
React.useState(0)
return React.createElement('p', props, 'namespace-import:esm')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "namespace-import-esm",
"exports": "./index.mjs"
}

0 comments on commit ed3ee38

Please sign in to comment.