Skip to content

Commit

Permalink
feat: Expose MetroConfig type directly from @react-native/metro-config (
Browse files Browse the repository at this point in the history
facebook#46602)

Summary:
React Native [app template provided by the CLI](https://github.com/react-native-community/template) currently uses [`metro-config` directly for `MetroConfig` type](https://github.com/react-native-community/template/blob/main/template/metro.config.js#L7).
However, it doesn't have `metro-config` as neither a dependency or dev dependency, which can lead to version mismatches.

While this is obviously a mistake on the template repo side, `metro-config` versions aren't matched with `react-native` versions. Therefore, getting the correct version of `metro-config` from `react-native/metro-config` would require reflecting on `react-native/metro-config`'s package.json etc. which is far from ideal. In my opinion it's would be much better to expose `MetroConfig` type from `react-native/metro-config` directly.

Version mismatching can happen in a monorepo setup. Say we have the monorepo structure using Yarn Modern:

```tree
.
├── RN75-app (workspace)
├── RN76-app (workspace)
│   ├── metro.config.js
│   └── node_modules
│       └── react-native
│           └── metro-config (0.76)
│               └── node_modules
│                   └── metro-config (version for 0.76)
└── node_modules
    ├── react-native
    │   └── metro-config (0.75)
    └── metro-config (version for 0.75)
```

`[email protected]` gets hoisted to the monorepo root while `[email protected]` sits in an RN 0.76 app workspace.

Say we have the following `RN76-app/metro.config.js` contents:

```js
const {getDefaultConfig, mergeConfig} = require('react-native/metro-config');

/**
 * Metro configuration
 * https://reactnative.dev/docs/metro
 *
 * type {import('metro-config').MetroConfig}
 */
const config = {};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);
```

In this case, `require('react-native/metro-config')` would resolve to `RN76-app/node_modules/react-native/node_modules/metro-config` since `react-native/metro-config` is a (dev) dependency of the App.

However `import('metro-config).MetroConfig` would resolve to `node_modules/metro-config` since it's not a direct dependency.

This is how we have a mismatch - imported functions come from different packages than imported type.

## Changelog:

[GENERAL] [ADDED] - Expose `MetroConfig` type directly from `react-native/metro-config`.

Pull Request resolved: facebook#46602

Test Plan:
`yarn build` to generate dist for `react-native/metro-config`, see it has the export of `MetroConfig`.

## Notes

If this PR gets approved, I'll submit relevant one to the CLI template.

Reviewed By: huntie

Differential Revision: D63258881

Pulled By: robhogan

fbshipit-source-id: e6f3c880eb4a0aa902c62932d58f243c38b07c2e
  • Loading branch information
tjzel authored and facebook-github-bot committed Oct 7, 2024
1 parent 7510ba3 commit cc6d1eb
Showing 1 changed file with 2 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/metro-config/src/index.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import type {ConfigT} from 'metro-config';

export type {MetroConfig} from 'metro-config';

import {getDefaultConfig as getBaseConfig, mergeConfig} from 'metro-config';

const INTERNAL_CALLSITES_REGEX = new RegExp(
Expand Down

0 comments on commit cc6d1eb

Please sign in to comment.