Skip to content

Turbopack: Generate a warning if both react-compiler and styled-jsx are enabled, suggest manually configuring them with babelrc#84006

Closed
bgw wants to merge 1 commit intobgw/reload-config-on-dev-server-restartfrom
bgw/warn-react-compiler-jsx
Closed

Turbopack: Generate a warning if both react-compiler and styled-jsx are enabled, suggest manually configuring them with babelrc#84006
bgw wants to merge 1 commit intobgw/reload-config-on-dev-server-restartfrom
bgw/warn-react-compiler-jsx

Conversation

@bgw
Copy link
Copy Markdown
Member

@bgw bgw commented Sep 20, 2025

I've decided this approach is a dead-end, but I'm putting the PR up here for reference.

Suggesting manual configuration of both babel plugins could serve as a stopgap solution for using react-compiler with styled-jsx.

But now I've realized that it's not really practical to ask the user to manually configure react-compiler with babel. We run babel transforms on both client+server, and there's no sane way to specify that a transform (react-compiler) is client-only in the babel configuration file format (the next/babel preset uses some webpack loader magic to pass down this information).

So instead, I need to go straight for the harder-but-"better" solution, which is to generate a warning, and to expose an option in compiler.styledJsx to use the babel implementation. Fortunately, #83502 already lays most of the groundwork needed for that.

…re enabled, suggest manually configuring them with babelrc
Copy link
Copy Markdown
Member Author

bgw commented Sep 20, 2025

Comment on lines +140 to +142
const text = session
.elementByCss('#react-compiler-enabled-message')
.text()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test code is missing await keywords, which will cause the text comparison to fail.

View Details
📝 Patch Details
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fceb9cd1a1..0741166ac5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -290,7 +290,7 @@ importers:
         version: 5.2.1(eslint@9.12.0(jiti@2.5.1))
       eslint-plugin-import:
         specifier: 2.31.0
-        version: 2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))
+        version: 2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
       eslint-plugin-jest:
         specifier: 27.6.3
         version: 27.6.3(@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))(jest@29.7.0(@types/node@20.17.6(patch_hash=rvl3vkomen3tospgr67bzubfyu))(babel-plugin-macros@3.1.0))(typescript@5.9.2)
@@ -660,7 +660,7 @@ importers:
         version: 9.12.0(jiti@2.5.1)
       eslint-config-next:
         specifier: canary
-        version: link:../../packages/eslint-config-next
+        version: 15.6.0-canary.19(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
       tailwindcss:
         specifier: 4.1.13
         version: 4.1.13
@@ -4401,6 +4401,9 @@ packages:
   '@next/env@15.5.3':
     resolution: {integrity: sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw==}
 
+  '@next/eslint-plugin-next@15.6.0-canary.19':
+    resolution: {integrity: sha512-oQ8YlBf8fad7UmfVRaIC6pio9LAIz2c/0UqHWFmA1bGb2zNHtiys3pitJKH38PKXeaXy//MwGKiiY+tVg5dD8Q==}
+
   '@next/swc-darwin-arm64@15.5.3':
     resolution: {integrity: sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg==}
     engines: {node: '>= 10'}
@@ -9210,6 +9213,15 @@ packages:
     engines: {node: '>=6.0'}
     hasBin: true
 
+  eslint-config-next@15.6.0-canary.19:
+    resolution: {integrity: sha512-JMoW38eXd9C5hCXZm9LGYEbWJ0cdYtAq8oPsSJ/Y8vuWEN455e17OrFngdWw4BrhXEqzaR5sKO+emD+AoE3cVA==}
+    peerDependencies:
+      eslint: ^7.23.0 || ^8.0.0 || ^9.0.0
+      typescript: '>=3.3.1'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
   eslint-formatter-codeframe@7.32.1:
     resolution: {integrity: sha512-DK/3Q3+zVKq/7PdSYiCxPrsDF8H/TRMK5n8Hziwr4IMkMy+XiKSwbpj25AdajS63I/B61Snetq4uVvX9fOLyAg==}
     engines: {node: ^10.12.0 || >=12.0.0}
@@ -14736,6 +14748,7 @@ packages:
     engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
     deprecated: |-
       You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.
+
       (For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
 
   qs@6.11.0:
@@ -21048,6 +21061,10 @@ snapshots:
 
   '@next/env@15.5.3': {}
 
+  '@next/eslint-plugin-next@15.6.0-canary.19':
+    dependencies:
+      fast-glob: 3.3.1
+
   '@next/swc-darwin-arm64@15.5.3':
     optional: true
 
@@ -26701,6 +26718,26 @@ snapshots:
     optionalDependencies:
       source-map: 0.6.1
 
+  eslint-config-next@15.6.0-canary.19(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2):
+    dependencies:
+      '@next/eslint-plugin-next': 15.6.0-canary.19
+      '@rushstack/eslint-patch': 1.10.4
+      '@typescript-eslint/eslint-plugin': 8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
+      '@typescript-eslint/parser': 8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
+      eslint: 9.12.0(jiti@2.5.1)
+      eslint-import-resolver-node: 0.3.9
+      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
+      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
+      eslint-plugin-jsx-a11y: 6.10.0(eslint@9.12.0(jiti@2.5.1))
+      eslint-plugin-react: 7.37.1(eslint@9.12.0(jiti@2.5.1))
+      eslint-plugin-react-hooks: 5.0.0(eslint@9.12.0(jiti@2.5.1))
+    optionalDependencies:
+      typescript: 5.9.2
+    transitivePeerDependencies:
+      - eslint-import-resolver-webpack
+      - eslint-plugin-import-x
+      - supports-color
+
   eslint-formatter-codeframe@7.32.1:
     dependencies:
       '@babel/code-frame': 7.12.11
@@ -26734,6 +26771,26 @@ snapshots:
       - eslint-import-resolver-webpack
       - supports-color
 
+  eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)):
+    dependencies:
+      '@nolyfill/is-core-module': 1.0.39
+      debug: 4.3.7
+      enhanced-resolve: 5.17.1
+      eslint: 9.12.0(jiti@2.5.1)
+      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
+      fast-glob: 3.3.2
+      get-tsconfig: 4.8.1
+      is-bun-module: 1.2.1
+      is-glob: 4.0.3
+    optionalDependencies:
+      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
+      eslint-plugin-import-x: 4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
+    transitivePeerDependencies:
+      - '@typescript-eslint/parser'
+      - eslint-import-resolver-node
+      - eslint-import-resolver-webpack
+      - supports-color
+
   eslint-mdx@3.1.5(eslint@9.12.0(jiti@2.5.1)):
     dependencies:
       acorn: 8.14.0
@@ -26766,13 +26823,14 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  eslint-module-utils@2.12.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.12.0(jiti@2.5.1)):
+  eslint-module-utils@2.12.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)):
     dependencies:
       debug: 3.2.7
     optionalDependencies:
       '@typescript-eslint/parser': 8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
       eslint: 9.12.0(jiti@2.5.1)
       eslint-import-resolver-node: 0.3.9
+      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
     transitivePeerDependencies:
       - supports-color
 
@@ -26800,6 +26858,24 @@ snapshots:
       - typescript
     optional: true
 
+  eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2):
+    dependencies:
+      '@typescript-eslint/utils': 8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2)
+      debug: 4.4.0
+      doctrine: 3.0.0
+      eslint: 9.12.0(jiti@2.5.1)
+      eslint-import-resolver-node: 0.3.9
+      get-tsconfig: 4.10.0
+      is-glob: 4.0.3
+      minimatch: 9.0.5
+      semver: 7.6.3
+      stable-hash: 0.0.4
+      tslib: 2.8.1
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    optional: true
+
   eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.16.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.12.0(jiti@2.5.1)):
     dependencies:
       '@rtsao/scc': 1.1.0
@@ -26829,7 +26905,7 @@ snapshots:
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)):
+  eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)):
     dependencies:
       '@rtsao/scc': 1.1.0
       array-includes: 3.1.8
@@ -26840,7 +26916,7 @@ snapshots:
       doctrine: 2.1.0
       eslint: 9.12.0(jiti@2.5.1)
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.12.0(jiti@2.5.1))
+      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.36.0(eslint@9.12.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1)))(eslint@9.12.0(jiti@2.5.1))
       hasown: 2.0.2
       is-core-module: 2.15.1
       is-glob: 4.0.3
diff --git a/test/e2e/react-compiler-with-styled-jsx/index.test.ts b/test/e2e/react-compiler-with-styled-jsx/index.test.ts
index 106b394974..26ed04ca91 100644
--- a/test/e2e/react-compiler-with-styled-jsx/index.test.ts
+++ b/test/e2e/react-compiler-with-styled-jsx/index.test.ts
@@ -137,7 +137,7 @@ describe('react-compiler-with-styled-jsx', () => {
       it('applies the react compiler transform', async () => {
         const session = await next.browser('/')
         await retry(async () => {
-          const text = session
+          const text = await session
             .elementByCss('#react-compiler-enabled-message')
             .text()
           expect(text).toMatch(/React compiler is enabled/)

Analysis

Missing await keyword causes test failure in elementByCss chain

What fails: session.elementByCss().text() chain on line 140-142 returns a Promise object instead of text string, causing expect(text).toMatch() to fail

How to reproduce:

# The test would fail because text is a Promise, not a string:
const text = session.elementByCss('#react-compiler-enabled-message').text()
expect(text).toMatch(/React compiler is enabled/) // Matches against Promise object

Result: Test assertion fails because regex match operates on Promise object instead of actual text content

Expected: Should await the full chain like other tests in the codebase: await session.elementByCss(...).text() to get the actual text string

Evidence: All other elementByCss usage in codebase consistently uses await before the entire chain - see test/development/acceptance-app/error-recovery.test.ts:431 and similar patterns

let $_: any
if (typeof window !== 'undefined') {
// eslint-disable-next-line no-eval
$_ = eval('typeof $ !== undefined ? $ : undefined')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$_ = eval('typeof $ !== undefined ? $ : undefined')
$_ = eval('typeof $ !== "undefined" ? $ : undefined')

The eval statement has a syntax error that will cause the React Compiler detection to fail.

View Details

Analysis

React Compiler detection fails due to incorrect typeof comparison

What fails: The eval statement in page.tsx line 11 compares typeof $ (string "undefined") to undefined (value), causing ReferenceError when $ is not defined

How to reproduce:

cd test/e2e/react-compiler-with-styled-jsx
node -e "eval('typeof $ !== undefined ? $ : undefined')"

Result: Throws ReferenceError: $ is not defined instead of returning undefined

Expected: Should return undefined when React Compiler hasn't injected the $ variable, allowing the detection logic to work properly

The issue occurs because typeof $ returns the string "undefined" when $ is not defined, but the code compares this to the value undefined. Since "undefined" !== undefined is true, the ternary tries to access $, which throws a ReferenceError.

@github-actions github-actions bot added the locked label Oct 7, 2025
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 7, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants