feat: compile the application with the React Compiler - #2015
feat: compile the application with the React Compiler#2015OliverDudgeon wants to merge 1 commit into
Conversation
|
This currently uses the babel plugin. We should use the new rust one via SWC. |
7d81b3e to
5cfd81a
Compare
5cfd81a to
66ee588
Compare
|
Pushed, still draft — this cannot land as it stands. The Two changes since the last push:
One finding that bears directly on #2020, recorded there in full: updating ketcher will not fix this. Still green on this branch: |
66ee588 to
9fe10ae
Compare
paper's published manifest declares no dependencies, optionalDependencies or peerDependencies at all — jsdom and canvas are devDependencies, which consumers never install. `dist/node/canvas.js` requires both anyway. The canvas require sits in a try/catch; the jsdom one does not, so bundlers resolve `jsdom/lib/jsdom/living/generated/utils` statically and nothing in this tree provides it. pnpm is behaving correctly. Flat hoisting would let any unrelated jsdom in the tree silently satisfy the unqualified require; pnpm's isolated node_modules cannot, so the upstream bug is unmaskable. The bug is latent under the current webpack build, because the sketcher never reaches the server compilation. It becomes fatal under Turbopack, which keeps it in the SSR graph — every failing import trace is an SSR one, never the browser graph. Landing the patch first means the Turbopack migration (#2015) never has to introduce the `turbopack.resolveAlias` workaround it currently carries. Patch the require with a `webpackIgnore: true` magic comment, which both webpack and Turbopack honour on `require()` expressions, so the specifier is left for Node to resolve at runtime instead of being bundled. Runtime behaviour is unchanged: the line is only reached once `require('canvas')` has succeeded, and installing canvas is what brings jsdom into the tree. Scoping is what makes this better than the alias. `resolveAlias` redirects the specifier for every importer in the graph, so a genuine jsdom consumer would silently receive a no-op stub. The patch touches only paper. Also delete `src/stubs/jsdom-utils.stub.js`, which the alias used to point at. It has been dead code here since 84a9309 removed the alias that referenced it, and the patch means nothing needs it again. Considered and rejected: declaring jsdom as a devDependency, and repairing paper's manifest via pnpm.packageExtensions. Both work, and both install a large tree and pin it to <=27 — the target is a jsdom internal, removed in 28 with no semver obligation — to satisfy a require that never executes. If a ketcher bump moves paper off 0.12.18, pnpm fails the install with ERR_PNPM_UNUSED_PATCH rather than silently reverting to a broken build. Worth fixing upstream regardless: paper should declare jsdom as an optionalDependency next to canvas, or not require it statically. Closes #2020 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
paper's published manifest declares no dependencies, optionalDependencies or peerDependencies at all — jsdom and canvas are devDependencies, which consumers never install. `dist/node/canvas.js` requires both anyway. The canvas require sits in a try/catch; the jsdom one does not, so bundlers resolve `jsdom/lib/jsdom/living/generated/utils` statically and nothing in this tree provides it. pnpm is behaving correctly. Flat hoisting would let any unrelated jsdom in the tree silently satisfy the unqualified require; pnpm's isolated node_modules cannot, so the upstream bug is unmaskable. The bug is latent under the current webpack build, because the sketcher never reaches the server compilation. It becomes fatal under Turbopack, which keeps it in the SSR graph — every failing import trace is an SSR one, never the browser graph. Landing the patch first means the Turbopack migration (#2015) never has to introduce the `turbopack.resolveAlias` workaround it currently carries. Patch the require with a `webpackIgnore: true` magic comment, which both webpack and Turbopack honour on `require()` expressions, so the specifier is left for Node to resolve at runtime instead of being bundled. Runtime behaviour is unchanged: the line is only reached once `require('canvas')` has succeeded, and installing canvas is what brings jsdom into the tree. Scoping is what makes this better than the alias. `resolveAlias` redirects the specifier for every importer in the graph, so a genuine jsdom consumer would silently receive a no-op stub. The patch touches only paper. Also delete `src/stubs/jsdom-utils.stub.js`, which the alias used to point at. It has been dead code here since 84a9309 removed the alias that referenced it, and the patch means nothing needs it again. Considered and rejected: declaring jsdom as a devDependency, and repairing paper's manifest via pnpm.packageExtensions. Both work, and both install a large tree and pin it to <=27 — the target is a jsdom internal, removed in 28 with no semver obligation — to satisfy a require that never executes. If a ketcher bump moves paper off 0.12.18, pnpm fails the install with ERR_PNPM_UNUSED_PATCH rather than silently reverting to a broken build. Worth fixing upstream regardless: paper should declare jsdom as an optionalDependency next to canvas, or not require it statically. Closes #2020 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
c2fe14c to
2120e75
Compare
2120e75 to
b29d8d1
Compare
dbefda4 to
3b4218a
Compare
Turns the React Compiler on as its native Rust port inside Turbopack, so there is no Babel plugin and no new dependency. `next.config.mjs` sets `reactCompiler: true` and `experimental.turbopackRustReactCompiler: true`, introduced in Next 16.3. Per the option's docs this runs the compiler as native code inside Turbopack, which `dev` already builds and serves with, so `babel-plugin-react-compiler` is not needed. The same docs state the option is only supported with Turbopack and throws under webpack, so the three `analyze` scripts give up their remaining `--webpack` pin. Builds on the compatibility work that turned on every `eslint-plugin-react-hooks` v7 diagnostic and cleared the tree, so no component is silently skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
b29d8d1 to
bba9b46
Compare
|
This is essentially working. However, the nextjs side is still marked as experimental. This can be promoted out of draft when that changes. |
Stacked on #2026 — merge that first. This PR is only the switch; the compatibility work that makes the switch safe lives there.
Turns the React Compiler on as its native Rust port inside Turbopack, so there is no Babel plugin and no new dependency.
Held back deliberately
experimental.turbopackRustReactCompileris marked experimental and "not recommended for production". This PR stays parked until that settles. #2026 carries all the actual code changes and can land without waiting.What it does
next.config.mjssetsreactCompiler: trueandexperimental.turbopackRustReactCompiler: true, introduced in Next 16.3. Per the option's docs, this runs the compiler as native code inside Turbopack, sobabel-plugin-react-compileris not needed.The same docs state the option "is only supported with Turbopack. Using it with webpack will throw an error." #2025 already moved
dev/buildto Turbopack, so the only remaining webpack pins are the threeanalyzescripts, which give theirs up here.Evidence it actually runs
next buildandnext devprint✓ turbopackRustReactCompiler.useMemoCacheappears 23 times across client chunks with the compiler on and 5 with it off (those 5 being React's own runtime export).next devis ready in ~215ms.Verification
pnpm lint(--max-warnings=0),pnpm tscandpnpm buildall pass.pnpm testis fully green: 238 acceptance, 808 node and component.🤖 Generated with Claude Code