Skip to content

Pass Metro's own @babel/runtime to Babel presets - #1957

Draft
robhogan wants to merge 1 commit into
mainfrom
pr1957
Draft

robhogan wants to merge 1 commit into
mainfrom
pr1957

Conversation

@robhogan

@robhogan robhogan commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

8388f71 added the metro: scheme resolver, which maps metro:babel-runtime/<path> to metro-runtime's own @babel/runtime. This is the Metro half of pointing @babel/plugin-transform-runtime at it - the preset half is react/react-native#57974, and until a preset reads it this is a no-op.

When transformer.enableBabelRuntime is true (the default), Metro now passes presets babelRuntimeModuleName: 'metro:babel-runtime' and that copy's installed version as Babel caller data, matching what @react-native/babel-preset reads. Caller data reaches a preset however it's configured, including from a project babel.config.js. The version is read from the installed package, so its package.json joins the transform cache key.

A string enableBabelRuntime (a version of the project's own @babel/runtime) keeps its meaning and passes neither. It's now documented as deprecated.

With presets importing from it, Metro's @babel/runtime needs to be in the file map, and Metro adds it as a root at startup when no configured root contains it. If that fails (eg the watcher can't watch it), Metro now warns and starts anyway, rather than failing for projects that never import from it.

Changelog:

 - **[Feature]**: When `transformer.enableBabelRuntime` is `true`, pass Metro's own `@babel/runtime` (`metro:babel-runtime`) and its installed version to Babel presets via caller data
 - **[Deprecated]**: String values of `transformer.enableBabelRuntime` (use `true`)

Test plan:
New integration test builds and runs a bundle through the full Metro + Babel pipeline, with a preset that reads the caller data as @react-native/babel-preset does. Its fixture uses import * as, whose helper @babel/runtime only exports from 7.14.0, so the helper is imported rather than inlined only if the version reaches the preset. Covered with enableBabelRuntime both true and false. Metro's @babel/runtime sits outside the test's watch folders, so this also exercises the dynamic root from #2065 end to end.

@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 Sep 21, 2026
@robhogan
robhogan force-pushed the pr1957 branch 2 times, most recently from d9dcf8f to cb7a1fe Compare September 21, 2026 14:34
@robhogan robhogan changed the title Pass metro:babel-runtime to Babel presets as the runtime module name via caller Pass Metro's own @babel/runtime and its version to Babel presets via caller Sep 21, 2026
@robhogan
robhogan force-pushed the pr1957 branch 2 times, most recently from 17e21c7 to fea257f Compare September 21, 2026 15:10
@robhogan robhogan changed the title Pass Metro's own @babel/runtime and its version to Babel presets via caller Pass Metro's own @babel/runtime to Babel presets Oct 16, 2026
@robhogan
robhogan changed the base branch from main to pr2065 October 16, 2026 10:35
8388f71 added the `metro:` scheme resolver, which maps `metro:babel-runtime/<path>` to metro-runtime's own `@babel/runtime`. This is the Metro half of pointing `@babel/plugin-transform-runtime` at it - the preset half is react/react-native#57974, and until a preset reads it this is a no-op.

When `transformer.enableBabelRuntime` is `true` (the default), Metro now passes presets `babelRuntimeModuleName: 'metro:babel-runtime'` and that copy's installed version as Babel caller data, matching what `@react-native/babel-preset` reads. Caller data reaches a preset however it's configured, including from a project `babel.config.js`. The version is read from the installed package, so its `package.json` joins the transform cache key.

A string `enableBabelRuntime` (a version of the project's own `@babel/runtime`) keeps its meaning and passes neither. It's now documented as deprecated.

With presets importing from it, Metro's `@babel/runtime` needs to be in the file map, and Metro adds it as a root at startup when no configured root contains it. If that fails (eg the watcher can't watch it), Metro now warns and starts anyway, rather than failing for projects that never import from it.

Changelog:
```
 - **[Feature]**: When `transformer.enableBabelRuntime` is `true`, pass Metro's own `@babel/runtime` (`metro:babel-runtime`) and its installed version to Babel presets via caller data
 - **[Deprecated]**: String values of `transformer.enableBabelRuntime` (use `true`)
```

Test plan:
New integration test builds and runs a bundle through the full Metro + Babel pipeline, with a preset that reads the caller data as `@react-native/babel-preset` does. Its fixture uses `import * as`, whose helper `@babel/runtime` only exports from 7.14.0, so the helper is imported rather than inlined only if the version reaches the preset. Covered with `enableBabelRuntime` both `true` and `false`. Metro's `@babel/runtime` sits outside the test's watch folders, so this also exercises the dynamic root from #2065 end to end.
@robhogan
robhogan changed the base branch from pr2065 to main October 16, 2026 10:52

This branch has not been deployed

No deployments
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant