diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts
index 63223dd363fc6..8cfdbb20cecdb 100644
--- a/packages/next/build/webpack-config.ts
+++ b/packages/next/build/webpack-config.ts
@@ -1256,11 +1256,16 @@ export default async function getBaseWebpackConfig(
}
}
- const shouldBeBundled = isResourceInPackages(
- res,
- config.experimental.transpilePackages,
- resolvedExternalPackageDirs
- )
+ // If a package is included in `transpilePackages`, we don't want to make it external.
+ // And also, if that resource is an ES module, we bundle it too because we can't
+ // rely on the require hook to alias `react` to our precompiled version.
+ const shouldBeBundled =
+ isResourceInPackages(
+ res,
+ config.experimental.transpilePackages,
+ resolvedExternalPackageDirs
+ ) ||
+ (isEsm && config.experimental.appDir)
if (/node_modules[/\\].*\.[mc]?js$/.test(res)) {
if (layer === WEBPACK_LAYERS.server) {
diff --git a/test/e2e/app-dir/rsc-external.test.ts b/test/e2e/app-dir/app-external.test.ts
similarity index 84%
rename from test/e2e/app-dir/rsc-external.test.ts
rename to test/e2e/app-dir/app-external.test.ts
index 7eb2160ea56ee..becf667a7140b 100644
--- a/test/e2e/app-dir/rsc-external.test.ts
+++ b/test/e2e/app-dir/app-external.test.ts
@@ -18,7 +18,7 @@ async function resolveStreamResponse(response: any, onData?: any) {
return result
}
-describe('app dir - rsc external dependency', () => {
+describe('app dir - external dependency', () => {
let next: NextInstance
if ((global as any).isNextDeploy) {
@@ -28,7 +28,7 @@ describe('app dir - rsc external dependency', () => {
beforeAll(async () => {
next = await createNext({
- files: new FileRef(path.join(__dirname, './rsc-external')),
+ files: new FileRef(path.join(__dirname, './app-external')),
dependencies: {
'@next/font': 'canary',
react: 'latest',
@@ -166,4 +166,30 @@ describe('app dir - rsc external dependency', () => {
)
).toMatch(/^__myFont_.{6}, __myFont_Fallback_.{6}$/)
})
+
+ describe('react in external esm packages', () => {
+ it('should use the same react in client app', async () => {
+ const html = await renderViaHTTP(next.url, '/esm/client')
+
+ const v1 = html.match(/App React Version: ([^<]+))[1]
+ const v2 = html.match(/External React Version: ([^<]+))[1]
+ expect(v1).toBe(v2)
+ })
+
+ it('should use the same react in server app', async () => {
+ const html = await renderViaHTTP(next.url, '/esm/server')
+
+ const v1 = html.match(/App React Version: ([^<]+))[1]
+ const v2 = html.match(/External React Version: ([^<]+))[1]
+ expect(v1).toBe(v2)
+ })
+
+ it('should use the same react in pages', async () => {
+ const html = await renderViaHTTP(next.url, '/test-pages-esm')
+
+ const v1 = html.match(/App React Version: ([^<]+))[1]
+ const v2 = html.match(/External React Version: ([^<]+))[1]
+ expect(v1).toBe(v2)
+ })
+ })
})
diff --git a/test/e2e/app-dir/rsc-external/app/css/[...slug]/page.js b/test/e2e/app-dir/app-external/app/css/[...slug]/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/css/[...slug]/page.js
rename to test/e2e/app-dir/app-external/app/css/[...slug]/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/css/modules/page.js b/test/e2e/app-dir/app-external/app/css/modules/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/css/modules/page.js
rename to test/e2e/app-dir/app-external/app/css/modules/page.js
diff --git a/test/e2e/app-dir/app-external/app/esm/client/page.js b/test/e2e/app-dir/app-external/app/esm/client/page.js
new file mode 100644
index 0000000000000..c768fe9d4716d
--- /dev/null
+++ b/test/e2e/app-dir/app-external/app/esm/client/page.js
@@ -0,0 +1,15 @@
+'use client'
+import { version, useValue } from 'esm-with-react'
+
+import React from 'react'
+
+export default function Index() {
+ const value = useValue()
+ return (
+
+
{'App React Version: ' + React.version}
+ {'External React Version: ' + version}
+ {'Test: ' + value}
+
+ )
+}
diff --git a/test/e2e/app-dir/app-external/app/esm/server/page.js b/test/e2e/app-dir/app-external/app/esm/server/page.js
new file mode 100644
index 0000000000000..fc89753d16a57
--- /dev/null
+++ b/test/e2e/app-dir/app-external/app/esm/server/page.js
@@ -0,0 +1,12 @@
+import { version } from 'esm-with-react'
+
+import React from 'react'
+
+export default function Index() {
+ return (
+
+
{'App React Version: ' + React.version}
+ {'External React Version: ' + version}
+
+ )
+}
diff --git a/test/e2e/app-dir/rsc-external/app/external-imports/client/page.js b/test/e2e/app-dir/app-external/app/external-imports/client/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/external-imports/client/page.js
rename to test/e2e/app-dir/app-external/app/external-imports/client/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/external-imports/server/page.js b/test/e2e/app-dir/app-external/app/external-imports/server/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/external-imports/server/page.js
rename to test/e2e/app-dir/app-external/app/external-imports/server/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/font/page.js b/test/e2e/app-dir/app-external/app/font/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/font/page.js
rename to test/e2e/app-dir/app-external/app/font/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/layout.js b/test/e2e/app-dir/app-external/app/layout.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/layout.js
rename to test/e2e/app-dir/app-external/app/layout.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/3rd-party-package/client.js b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/client.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/3rd-party-package/client.js
rename to test/e2e/app-dir/app-external/app/react-server/3rd-party-package/client.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/3rd-party-package/page.js b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/3rd-party-package/page.js
rename to test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/client-detector.js b/test/e2e/app-dir/app-external/app/react-server/client-detector.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/client-detector.js
rename to test/e2e/app-dir/app-external/app/react-server/client-detector.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/detector.js b/test/e2e/app-dir/app-external/app/react-server/detector.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/detector.js
rename to test/e2e/app-dir/app-external/app/react-server/detector.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/optout/client.js b/test/e2e/app-dir/app-external/app/react-server/optout/client.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/optout/client.js
rename to test/e2e/app-dir/app-external/app/react-server/optout/client.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/optout/page.js b/test/e2e/app-dir/app-external/app/react-server/optout/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/optout/page.js
rename to test/e2e/app-dir/app-external/app/react-server/optout/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/react-server/page.js b/test/e2e/app-dir/app-external/app/react-server/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/react-server/page.js
rename to test/e2e/app-dir/app-external/app/react-server/page.js
diff --git a/test/e2e/app-dir/rsc-external/app/shared-esm-dep/page.js b/test/e2e/app-dir/app-external/app/shared-esm-dep/page.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/app/shared-esm-dep/page.js
rename to test/e2e/app-dir/app-external/app/shared-esm-dep/page.js
diff --git a/test/e2e/app-dir/rsc-external/components/random-module-instance.js b/test/e2e/app-dir/app-external/components/random-module-instance.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/components/random-module-instance.js
rename to test/e2e/app-dir/app-external/components/random-module-instance.js
diff --git a/test/e2e/app-dir/rsc-external/next.config.js b/test/e2e/app-dir/app-external/next.config.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/next.config.js
rename to test/e2e/app-dir/app-external/next.config.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/index.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/index.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/index.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/index.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/index.server.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/index.server.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/index.server.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/index.server.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/subpath.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/subpath.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/subpath.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/subpath.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/subpath.server.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/subpath.server.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports-optout/subpath.server.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/subpath.server.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/dep.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/dep.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/dep.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/dep.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/dep.server.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/dep.server.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/dep.server.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/dep.server.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/index.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/index.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/index.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/index.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/index.server.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/index.server.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/index.server.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/index.server.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/subpath.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/subpath.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/subpath.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/subpath.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/subpath.server.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/subpath.server.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/conditional-exports/subpath.server.js
rename to test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/subpath.server.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/css/index.js b/test/e2e/app-dir/app-external/node_modules_bak/css/index.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/css/index.js
rename to test/e2e/app-dir/app-external/node_modules_bak/css/index.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/css/module.js b/test/e2e/app-dir/app-external/node_modules_bak/css/module.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/css/module.js
rename to test/e2e/app-dir/app-external/node_modules_bak/css/module.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/css/package.json b/test/e2e/app-dir/app-external/node_modules_bak/css/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/css/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/css/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/css/style.css b/test/e2e/app-dir/app-external/node_modules_bak/css/style.css
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/css/style.css
rename to test/e2e/app-dir/app-external/node_modules_bak/css/style.css
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/css/styles.module.css b/test/e2e/app-dir/app-external/node_modules_bak/css/styles.module.css
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/css/styles.module.css
rename to test/e2e/app-dir/app-external/node_modules_bak/css/styles.module.css
diff --git a/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/index.js b/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/index.js
new file mode 100644
index 0000000000000..a82da124dde34
--- /dev/null
+++ b/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/index.js
@@ -0,0 +1,6 @@
+import React from 'react'
+
+const Context = React.createContext ? React.createContext('hello') : null
+
+export const version = React.version
+export const useValue = () => React.useContext(Context)
diff --git a/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/package.json b/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/package.json
new file mode 100644
index 0000000000000..54a365f710e06
--- /dev/null
+++ b/test/e2e/app-dir/app-external/node_modules_bak/esm-with-react/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "esm-with-react",
+ "type": "module",
+ "exports": "./index.js",
+ "dependencies": {
+ "react": "^18",
+ "react-dom": "^18"
+ }
+}
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/font/index.ts b/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/font/index.ts
rename to test/e2e/app-dir/app-external/node_modules_bak/font/index.ts
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/font/my-font.woff2 b/test/e2e/app-dir/app-external/node_modules_bak/font/my-font.woff2
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/font/my-font.woff2
rename to test/e2e/app-dir/app-external/node_modules_bak/font/my-font.woff2
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/font/package.json b/test/e2e/app-dir/app-external/node_modules_bak/font/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/font/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/font/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/browser.js b/test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/browser.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/browser.js
rename to test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/browser.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/index.js b/test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/index.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/index.js
rename to test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/index.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/index.mjs b/test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/index.mjs
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/index.mjs
rename to test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/index.mjs
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/package.json b/test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/non-isomorphic-text/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/non-isomorphic-text/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/random-module-instance/index.js b/test/e2e/app-dir/app-external/node_modules_bak/random-module-instance/index.js
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/random-module-instance/index.js
rename to test/e2e/app-dir/app-external/node_modules_bak/random-module-instance/index.js
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/random-module-instance/package.json b/test/e2e/app-dir/app-external/node_modules_bak/random-module-instance/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/random-module-instance/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/random-module-instance/package.json
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/untranspiled-module/index.ts b/test/e2e/app-dir/app-external/node_modules_bak/untranspiled-module/index.ts
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/untranspiled-module/index.ts
rename to test/e2e/app-dir/app-external/node_modules_bak/untranspiled-module/index.ts
diff --git a/test/e2e/app-dir/rsc-external/node_modules_bak/untranspiled-module/package.json b/test/e2e/app-dir/app-external/node_modules_bak/untranspiled-module/package.json
similarity index 100%
rename from test/e2e/app-dir/rsc-external/node_modules_bak/untranspiled-module/package.json
rename to test/e2e/app-dir/app-external/node_modules_bak/untranspiled-module/package.json
diff --git a/test/e2e/app-dir/app-external/pages/test-pages-esm.jsx b/test/e2e/app-dir/app-external/pages/test-pages-esm.jsx
new file mode 100644
index 0000000000000..2a8d016df9225
--- /dev/null
+++ b/test/e2e/app-dir/app-external/pages/test-pages-esm.jsx
@@ -0,0 +1,14 @@
+import { version, useValue } from 'esm-with-react'
+
+import React from 'react'
+
+export default function Index() {
+ const value = useValue()
+ return (
+
+
{'App React Version: ' + React.version}
+ {'External React Version: ' + version}
+ {'Test: ' + value}
+
+ )
+}
diff --git a/test/e2e/app-dir/rsc-external/pages/test-pages.jsx b/test/e2e/app-dir/app-external/pages/test-pages.jsx
similarity index 100%
rename from test/e2e/app-dir/rsc-external/pages/test-pages.jsx
rename to test/e2e/app-dir/app-external/pages/test-pages.jsx