Skip to content

Babel preset: don't override dev based on omission of redundant withDevTools, infer from env() instead.#55805

Closed
robhogan wants to merge 1 commit intomainfrom
export-D94660480
Closed

Babel preset: don't override dev based on omission of redundant withDevTools, infer from env() instead.#55805
robhogan wants to merge 1 commit intomainfrom
export-D94660480

Conversation

@robhogan
Copy link
Contributor

Summary:
Currently the RN Babel preset has this surprising bit of behaviour:

module.exports = (options, babel) => {
  if (options.withDevTools == null) {
    const env = process.env.BABEL_ENV || process.env.NODE_ENV;
    if (!env || env === 'development') {
      return getPreset(null, {...options, dev: true}, babel);
    }
  }
  return getPreset(null, options, babel);
};

If the (undocumented, otherwise unused) withDevTools option is set (to anything), we will override any given value of dev to true if BABEL_ENV || NODE_ENV || 'development' === 'development'.

To put that another way, with NODE_ENV=development and BABEL_ENV unset, we would always produce a dev bundle even if { dev: false }

Expo sets withDevTools: false to stop this happening, and always set dev (so this diff means no observable change under Expo):

https://github.com/expo/expo/blob/4a46dbff7a5a77d9fe06d30a70d7fab38cfc7f9a/packages/babel-preset-expo/build/index.js#L235-L236

This odd-looking override was introduced in 2017 in bc22a4d / D5237158 as a way to gate babel/plugin-transform-react-jsx-source, before the preset accepted any other options - it was never intended to override dev. Now, we gate that same plugin under options.dev.

Inferring dev when unspecified

The one potentially load-bearing piece of this is that, when a consumer specifies neither withDevTools nor dev (or maybe no options at all), this code serves to infer it from process.env.BABEL_ENV || process.env.NODE_ENV, which is reasonable and actually closer to the way typical plugins/presets work, but a better mechanism is to use the env() API (which defaults to process.env.BABEL_ENV || process.env.NODE_ENV).

https://babeljs.io/docs/config-files#apienv

This change

  • Removes the obsolete use of withDevToolss, and never overrides the explicitly-passed dev
  • Where dev is not specified, falls back to the Babel environment.

Changelog:
[General][Fixed] Babel-preset: Don't override explicitly-passed dev config if obsolete withDevTools is missing

Differential Revision: D94660480

…thDevTools`, infer from `env()` instead.

Summary:
Currently the RN Babel preset has this surprising bit of behaviour:

```js
module.exports = (options, babel) => {
  if (options.withDevTools == null) {
    const env = process.env.BABEL_ENV || process.env.NODE_ENV;
    if (!env || env === 'development') {
      return getPreset(null, {...options, dev: true}, babel);
    }
  }
  return getPreset(null, options, babel);
};
```

If the (undocumented, otherwise unused) `withDevTools` option is set (to anything), we will override any given value of `dev` to `true` if `BABEL_ENV` || `NODE_ENV || 'development' === 'development'`.

To put that another way, with `NODE_ENV=development` and `BABEL_ENV` unset, we would always produce a dev bundle even if `{ dev: false }`

Expo sets `withDevTools: false` to stop this happening, and always set `dev` (so this diff means **no observable change under Expo**):

https://github.com/expo/expo/blob/4a46dbff7a5a77d9fe06d30a70d7fab38cfc7f9a/packages/babel-preset-expo/build/index.js#L235-L236

This odd-looking override was introduced in 2017 in bc22a4d / D5237158 as a way to gate `babel/plugin-transform-react-jsx-source`, *before the preset accepted any other options* - it was never intended to override `dev`. Now, we gate that same plugin under `options.dev`.

## Inferring `dev` when unspecified

The one potentially load-bearing piece of this is that, when a consumer specifies neither `withDevTools` nor `dev` (or maybe no options at all), this code serves to infer it from `process.env.BABEL_ENV || process.env.NODE_ENV`, which is reasonable and actually closer to the way typical plugins/presets work, but a better mechanism is to use the `env()` API (which defaults to `process.env.BABEL_ENV || process.env.NODE_ENV`).

https://babeljs.io/docs/config-files#apienv

## This change
 - Removes the obsolete use of `withDevToolss`, and never overrides the explicitly-passed `dev`
 - Where `dev` is not specified, falls back to the Babel environment.

Changelog:
[General][Fixed] Babel-preset: Don't override explicitly-passed `dev` config if obsolete `withDevTools` is missing

Differential Revision: D94660480
@meta-codesync
Copy link

meta-codesync bot commented Feb 27, 2026

@robhogan has exported this pull request. If you are a Meta employee, you can view the originating Diff in D94660480.

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Feb 27, 2026
meta-codesync bot pushed a commit that referenced this pull request Feb 27, 2026
…hDevTools`, infer from `env()` instead. (#55805)

Summary:

Currently the RN Babel preset has this surprising bit of behaviour:

```js
module.exports = (options, babel) => {
  if (options.withDevTools == null) {
    const env = process.env.BABEL_ENV || process.env.NODE_ENV;
    if (!env || env === 'development') {
      return getPreset(null, {...options, dev: true}, babel);
    }
  }
  return getPreset(null, options, babel);
};
```

If the (undocumented, otherwise unused) `withDevTools` option is set (to anything), we will override any given value of `dev` to `true` if `BABEL_ENV` || `NODE_ENV || 'development' === 'development'`.

To put that another way, with `NODE_ENV=development` and `BABEL_ENV` unset, we would always produce a dev bundle even if `{ dev: false }`

Expo sets `withDevTools: false` to stop this happening, and always set `dev` (so this diff means **no observable change under Expo**):

https://github.com/expo/expo/blob/4a46dbff7a5a77d9fe06d30a70d7fab38cfc7f9a/packages/babel-preset-expo/build/index.js#L235-L236

This odd-looking override was introduced in 2017 in bc22a4d / D5237158 as a way to gate `babel/plugin-transform-react-jsx-source`, *before the preset accepted any other options* - it was never intended to override `dev`. Now, we gate that same plugin under `options.dev`.

## Inferring `dev` when unspecified

The one potentially load-bearing piece of this is that, when a consumer specifies neither `withDevTools` nor `dev` (or maybe no options at all), this code serves to infer it from `process.env.BABEL_ENV || process.env.NODE_ENV`, which is reasonable and actually closer to the way typical plugins/presets work, but a better mechanism compatible with Babel's cache is to use the `env()` API (which defaults to `process.env.BABEL_ENV || process.env.NODE_ENV`, so preserves behaviour).

https://babeljs.io/docs/config-files#apienv

## This change
 - Removes the obsolete use of `withDevToolss`, and never overrides the explicitly-passed `dev`
 - Where `dev` is not specified, falls back to the Babel environment.

Changelog:
[General][Fixed] Babel-preset: Don't override explicitly-passed `dev` config if obsolete `withDevTools` is missing

Reviewed By: huntie

Differential Revision: D94660480
meta-codesync bot pushed a commit that referenced this pull request Feb 27, 2026
…t mutate `process.env.BABEL_ENV`

Summary:
After #55805, the RN Babel preset no longer reads `process.env.BABEL_ENV` directly, instead using Babel's `env()` API, which is both cache-aware and properly respects explicit `envName` config.

See:
 - https://babeljs.io/docs/config-files#apienv
 - https://babeljs.io/docs/options#envname

Now, instead of mutating `process.env.BABEL_ENV` to force the environment for a transform, we can specify `envName` instead.

Changelog: [Internal]

Differential Revision: D94662935
@meta-codesync meta-codesync bot closed this in c5a38ab Feb 28, 2026
@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label Feb 28, 2026
@meta-codesync
Copy link

meta-codesync bot commented Feb 28, 2026

This pull request has been merged in c5a38ab.

meta-codesync bot pushed a commit that referenced this pull request Mar 2, 2026
…t mutate `process.env.BABEL_ENV` (#55806)

Summary:

After #55805, the RN Babel preset no longer reads `process.env.BABEL_ENV` directly, instead using Babel's `env()` API, which is both cache-aware and properly respects explicit `envName` config.

See:
 - https://babeljs.io/docs/config-files#apienv
 - https://babeljs.io/docs/options#envname

Now, instead of mutating `process.env.BABEL_ENV` to force the environment for a transform (and having to worry about restoring it to avoid side-effects), we can just specify `envName` instead.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D94662935
meta-codesync bot pushed a commit that referenced this pull request Mar 2, 2026
…t mutate `process.env.BABEL_ENV` (#55806)

Summary:
Pull Request resolved: #55806

After #55805, the RN Babel preset no longer reads `process.env.BABEL_ENV` directly, instead using Babel's `env()` API, which is both cache-aware and properly respects explicit `envName` config.

See:
 - https://babeljs.io/docs/config-files#apienv
 - https://babeljs.io/docs/options#envname

Now, instead of mutating `process.env.BABEL_ENV` to force the environment for a transform (and having to worry about restoring it to avoid side-effects), we can just specify `envName` instead.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D94662935

fbshipit-source-id: 598a8dd53e33e4b5edfe62778a61c6bf3c48a4e7
zoontek pushed a commit to zoontek/react-native that referenced this pull request Mar 9, 2026
…hDevTools`, infer from `env()` instead. (facebook#55805)

Summary:
Pull request resolved: facebook#55805

Currently the RN Babel preset has this surprising bit of behaviour:

```js
module.exports = (options, babel) => {
  if (options.withDevTools == null) {
    const env = process.env.BABEL_ENV || process.env.NODE_ENV;
    if (!env || env === 'development') {
      return getPreset(null, {...options, dev: true}, babel);
    }
  }
  return getPreset(null, options, babel);
};
```

If the (undocumented, otherwise unused) `withDevTools` option is set (to anything), we will override any given value of `dev` to `true` if `BABEL_ENV` || `NODE_ENV || 'development' === 'development'`.

To put that another way, with `NODE_ENV=development` and `BABEL_ENV` unset, we would always produce a dev bundle even if `{ dev: false }`

Expo sets `withDevTools: false` to stop this happening, and always set `dev` (so this diff means **no observable change under Expo**):

https://github.com/expo/expo/blob/4a46dbff7a5a77d9fe06d30a70d7fab38cfc7f9a/packages/babel-preset-expo/build/index.js#L235-L236

This odd-looking override was introduced in 2017 in facebook@bc22a4d / D5237158 as a way to gate `babel/plugin-transform-react-jsx-source`, *before the preset accepted any other options* - it was never intended to override `dev`. Now, we gate that same plugin under `options.dev`.

## Inferring `dev` when unspecified

The one potentially load-bearing piece of this is that, when a consumer specifies neither `withDevTools` nor `dev` (or maybe no options at all), this code serves to infer it from `process.env.BABEL_ENV || process.env.NODE_ENV`, which is reasonable and actually closer to the way typical plugins/presets work, but a better mechanism compatible with Babel's cache is to use the `env()` API (which defaults to `process.env.BABEL_ENV || process.env.NODE_ENV`, so preserves behaviour).

https://babeljs.io/docs/config-files#apienv

## This change
 - Removes the obsolete use of `withDevToolss`, and never overrides the explicitly-passed `dev`
 - Where `dev` is not specified, falls back to the Babel environment.

Changelog:
[General][Fixed] Babel-preset: Don't override explicitly-passed `dev` config if obsolete `withDevTools` is missing

Reviewed By: huntie

Differential Revision: D94660480

fbshipit-source-id: 5dfae8fb704e6881b03120cd14510795382a98ba
zoontek pushed a commit to zoontek/react-native that referenced this pull request Mar 9, 2026
…t mutate `process.env.BABEL_ENV` (facebook#55806)

Summary:
Pull Request resolved: facebook#55806

After facebook#55805, the RN Babel preset no longer reads `process.env.BABEL_ENV` directly, instead using Babel's `env()` API, which is both cache-aware and properly respects explicit `envName` config.

See:
 - https://babeljs.io/docs/config-files#apienv
 - https://babeljs.io/docs/options#envname

Now, instead of mutating `process.env.BABEL_ENV` to force the environment for a transform (and having to worry about restoring it to avoid side-effects), we can just specify `envName` instead.

Changelog: [Internal]

Reviewed By: javache

Differential Revision: D94662935

fbshipit-source-id: 598a8dd53e33e4b5edfe62778a61c6bf3c48a4e7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants