Skip to content

Conversation

@josephsavona
Copy link
Member

@josephsavona josephsavona commented Nov 12, 2025

This deprecates the noEmit: boolean flag and adds outputMode: 'client' | 'client-no-memo' | 'ssr' | 'lint' as the replacement. OutputMode defaults to null and takes precedence if specified, otherwise we use 'client' mode for noEmit=false and 'lint' mode for noEmit=true.

Key points:

  • Retrying failed compilation switches from 'client' mode to 'client-no-memo'
  • Validations are enabled behind Environment.proto.shouldEnableValidations, enabled for all modes except 'client-no-memo'. Similar for dropping manual memoization.
  • OptimizeSSR is now gated by the outputMode==='ssr', not a feature flag
  • Creation of reactive scopes, and related codegen logic, is now gated by outputMode==='client'

@meta-cla meta-cla bot added the CLA Signed label Nov 12, 2025
@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Nov 12, 2025
@react-sizebot
Copy link

react-sizebot commented Nov 12, 2025

Comparing: 4cf770d...2782d93

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 608.36 kB 608.36 kB = 107.68 kB 107.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 667.47 kB 667.47 kB = 117.57 kB 117.57 kB
facebook-www/ReactDOM-prod.classic.js = 693.67 kB 693.67 kB = 122.07 kB 122.07 kB
facebook-www/ReactDOM-prod.modern.js = 684.10 kB 684.10 kB = 120.45 kB 120.45 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 2782d93

@josephsavona josephsavona force-pushed the pr35112 branch 5 times, most recently from 88dec31 to 4257115 Compare November 13, 2025 22:54
@josephsavona josephsavona changed the title [compiler] Replace noEmit with outputMode [compiler] Deprecate noEmit, add outputMode Nov 13, 2025
@josephsavona josephsavona force-pushed the pr35112 branch 4 times, most recently from 1a204bc to 9130e66 Compare November 14, 2025 16:36
if (programContext.hasModuleScopeOptOut) {
return null;
} else if (programContext.opts.noEmit) {
} else if (programContext.opts.outputMode === 'lint') {
Copy link
Member Author

Choose a reason for hiding this comment

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

i honestly don't quite get the point of this case, i'm just preserving what we did before

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this might have been the IDE prototype @poteto built to highlight effect dependencies

Copy link
Contributor

@mofeiZ mofeiZ left a comment

Choose a reason for hiding this comment

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

Makes sense

## Error

```
Found 1 error:
Copy link
Member Author

Choose a reason for hiding this comment

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

This preserves the existing error (previous test was @noEmit). Also see the infer-effect-deps-with-rule-violation-use-memo-opt-in.js which uses outputMode:'client', and does actually infer effect deps

josephsavona added a commit that referenced this pull request Nov 20, 2025
Just a quick poc:
* Inline useState when the initializer is known to not be a function.
The heuristic could be improved but will handle a large number of cases
already.
* Prune effects
* Prune useRef if the ref is unused, by pruning 'ref' props on primitive
components. Then DCE does the rest of the work - with a small change to
allow `useRef()` calls to be dropped since function calls aren't
normally eligible for dropping.
* Prune event handlers, by pruning props whose names start w "on" from
primitive components. Then DCE removes the functions themselves.

Per the fixture, this gets pretty far.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35102).
* #35112
* __->__ #35102
This deprecates the `noEmit: boolean` flag and adds `outputMode: 'client' | 'client-no-memo' | 'ssr' | 'lint'` as the replacement. OutputMode defaults to null and takes precedence if specified, otherwise we use 'client' mode for noEmit=false and 'lint' mode for noEmit=true.

Key points:
* Retrying failed compilation switches from 'client' mode to 'client-no-memo'
* Validations are enabled behind Environment.proto.shouldEnableValidations, enabled for all modes except 'client-no-memo'. Similar for dropping manual memoization.
* OptimizeSSR is now gated by the outputMode==='ssr', not a feature flag
* Creation of reactive scopes, and related codegen logic, is now gated by outputMode==='client'
github-actions bot pushed a commit that referenced this pull request Nov 20, 2025
Just a quick poc:
* Inline useState when the initializer is known to not be a function.
The heuristic could be improved but will handle a large number of cases
already.
* Prune effects
* Prune useRef if the ref is unused, by pruning 'ref' props on primitive
components. Then DCE does the rest of the work - with a small change to
allow `useRef()` calls to be dropped since function calls aren't
normally eligible for dropping.
* Prune event handlers, by pruning props whose names start w "on" from
primitive components. Then DCE removes the functions themselves.

Per the fixture, this gets pretty far.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35102).
* #35112
* __->__ #35102

DiffTrain build for [4cf770d](4cf770d)
github-actions bot pushed a commit that referenced this pull request Nov 20, 2025
Just a quick poc:
* Inline useState when the initializer is known to not be a function.
The heuristic could be improved but will handle a large number of cases
already.
* Prune effects
* Prune useRef if the ref is unused, by pruning 'ref' props on primitive
components. Then DCE does the rest of the work - with a small change to
allow `useRef()` calls to be dropped since function calls aren't
normally eligible for dropping.
* Prune event handlers, by pruning props whose names start w "on" from
primitive components. Then DCE removes the functions themselves.

Per the fixture, this gets pretty far.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35102).
* #35112
* __->__ #35102

DiffTrain build for [4cf770d](4cf770d)
@josephsavona josephsavona merged commit 50e7ec8 into main Nov 20, 2025
265 of 282 checks passed
github-actions bot pushed a commit that referenced this pull request Nov 20, 2025
This deprecates the `noEmit: boolean` flag and adds `outputMode:
'client' | 'client-no-memo' | 'ssr' | 'lint'` as the replacement.
OutputMode defaults to null and takes precedence if specified, otherwise
we use 'client' mode for noEmit=false and 'lint' mode for noEmit=true.

Key points:
* Retrying failed compilation switches from 'client' mode to
'client-no-memo'
* Validations are enabled behind
Environment.proto.shouldEnableValidations, enabled for all modes except
'client-no-memo'. Similar for dropping manual memoization.
* OptimizeSSR is now gated by the outputMode==='ssr', not a feature flag
* Creation of reactive scopes, and related codegen logic, is now gated
by outputMode==='client'

DiffTrain build for [50e7ec8](50e7ec8)
github-actions bot pushed a commit that referenced this pull request Nov 20, 2025
This deprecates the `noEmit: boolean` flag and adds `outputMode:
'client' | 'client-no-memo' | 'ssr' | 'lint'` as the replacement.
OutputMode defaults to null and takes precedence if specified, otherwise
we use 'client' mode for noEmit=false and 'lint' mode for noEmit=true.

Key points:
* Retrying failed compilation switches from 'client' mode to
'client-no-memo'
* Validations are enabled behind
Environment.proto.shouldEnableValidations, enabled for all modes except
'client-no-memo'. Similar for dropping manual memoization.
* OptimizeSSR is now gated by the outputMode==='ssr', not a feature flag
* Creation of reactive scopes, and related codegen logic, is now gated
by outputMode==='client'

DiffTrain build for [50e7ec8](50e7ec8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants