Support array-exporting config files (RFC)#1753
Conversation
Summary: These have been deprecated (with a runtime warning) and removal planned for a year now. I believe they're little used in the wild and inherently very limited. Expo has already dropped support. Removing YAML support lets us drop a dependency also. Changelog: ``` - **[Breaking]**: Remove support for YAML and `.es6` config files ``` Differential Revision: D109987702
Summary: Back in #1580 ("future?"), I floated the idea of a Metro config sugar using an array-valued export. This implements that, on top of the ESM support and TS support added over the last few months (but not announced yet). One hesitation - I'm wary of having too many ways to do the same thing, so this is part RFC. However, IMO, this is a sufficient improvement to warrant a bit of churn, it's purely additive for now but ought to replace `mergeConfig` in the long term. The [recommended Metro config for RN](https://reactnative.dev/docs/metro) is currently: ```js // metro.config.js const { getDefaultConfig, mergeConfig, } = require('react-native/metro-config'); /** * Metro configuration * https://metrobundler.dev/docs/configuration * * type {import('metro-config').MetroConfig} */ const config = {}; module.exports = mergeConfig(getDefaultConfig(__dirname), config); ``` This could be: ```typescript // metro.config.mts /** * Metro configuration * https://metrobundler.dev/docs/configuration */ import type {MetroConfig} from 'metro'; export default [ await import('react-native/metro-config'), defaults => ({ // Your config here. }) ] satisfies MetroConfig; ``` That's fully type checked and extensible. ## Benefits - No need to pass in the project root into framework defaults (`__dirname`/`import.meta.dirname`) - because the config loader already infers that into `projectRoot` based on the location of the config file, and downstream config functions are given fully-hydrated configs, including `projectRoot`. (If it needs to be overridden, it can be via the first entry) - No need to import `getDefaultConfig` or `mergeConfig` - and (in future?) no need for RN to (re-)export them. ## Libraries For libraries that need to modify Metro config, currently the popular pattern is a decorator: ```js // metro.config.js const { getDefaultConfig, mergeConfig, } = require('react-native/metro-config'); const { wrapWithReanimatedMetroConfig, } = require('react-native-reanimated/metro-config'); /** * Metro configuration * https://metrobundler.dev/docs/configuration * * type {import('metro-config').MetroConfig} */ const config = mergeConfig(getDefaultConfig(__dirname), {}); module.exports = wrapWithReanimatedMetroConfig(config); ``` This could be: ```typescript // metro.config.mts /** * Metro configuration * https://metrobundler.dev/docs/configuration */ import type {MetroConfig} from 'metro'; export default [ await import('react-native/metro-config'), defaults => ({ // Your config here. }), await import('react-native-reanimated/metro-config'), // Reanimated would need to support this by exporting a default function. ] satisfies MetroConfig; ``` ## Why now? We just bumped minimum Node.js for Metro/RN to 22.13 - that means TypeScript is supported everywhere. To minimise churn, I think ideally we announce the new recommended format all at once with the next RN release - ESM + TS (+ array form). Differential Revision: D109989571
|
@robhogan has exported this pull request. If you are a Meta employee, you can view the originating Diff in D109989571. |
|
I'm not sure we've seen a good use-case for this yet. I believe the main thing we've seen (and implemented) was an override env var, which can then itself wrap the user config, assuming it exports a function. We may still revisit and tweak that, but this was important, for example, for Radon IDE We did recently remove more ways of defining a Metro config by replacing the loading code, partially to unify all config loaders to one code path, and partially because we felt there were too many config formats already 😅 Edit: re config composition, I find it unlikely we'd offer users to customise the Metro config (or encourage it as such) indefinitely. Users typically don't have deep knowledge of Metro, and library authors can easily cause bugs that then make their way back to us, so we're assuming that eventually we'll need to build our own config and plugin format on top of Metro, to lock things down. Mainly, that means, I think it's unlikely we'd let things go as far as allowing many libraries to modify the Metro config like this without stepping in and taking some action |
Summary:
Back in #1580 ("future?"), I floated the idea of a Metro config sugar using an array-valued export.
This implements that, on top of the ESM support and TS support added over the last few months (but not announced yet).
One hesitation - I'm wary of having too many ways to do the same thing, so this is part RFC. However, IMO, this is a sufficient improvement to warrant a bit of churn, it's purely additive for now but ought to replace
mergeConfigin the long term.The recommended Metro config for RN is currently:
This could be:
That's fully type checked and extensible.
Benefits
__dirname/import.meta.dirname) - because the config loader already infers that intoprojectRootbased on the location of the config file, and downstream config functions are given fully-hydrated configs, includingprojectRoot. (If it needs to be overridden, it can be via the first entry)getDefaultConfigormergeConfig- and (in future?) no need for RN to (re-)export them.Libraries
For libraries that need to modify Metro config, currently the popular pattern is a decorator:
This could be:
Why now?
We just bumped minimum Node.js for Metro/RN to 22.13 - that means TypeScript is supported everywhere. To minimise churn, I think ideally we announce the new recommended format all at once with the next RN release - ESM + TS (+ array form).
Differential Revision: D109989571