react-native/packages/metro-config
Tomasz Żelawski cc6d1eb844 feat: Expose MetroConfig type directly from @react-native/metro-config (#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)
```

`react-native@0.75` gets hoisted to the monorepo root while `react-native@0.76` 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: https://github.com/facebook/react-native/pull/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
2024-10-07 06:35:01 -07:00
..
src feat: Expose MetroConfig type directly from @react-native/metro-config (#46602) 2024-10-07 06:35:01 -07:00
.gitignore Move metro-config package into monorepo build, enable TS generation (#41836) 2024-02-12 05:20:38 -08:00
package.json Bump Metro to 0.81.0-alpha.2 (#46703) 2024-10-01 11:27:41 -07:00
README.md

@react-native/metro-config

Version

Installation

yarn add --dev @react-native/js-polyfills metro-config @react-native/metro-babel-transformer metro-runtime @react-native/metro-config

Note: We're using yarn to install deps. Feel free to change commands to use npm 3+ and npx if you like

Testing

To run the tests in this package, run the following commands from the React Native root folder:

  1. yarn to install the dependencies. You just need to run this once
  2. yarn jest packages/metro-config.