You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
metro-config: Accept functions as arguments to mergeConfig (#1580)
Summary:
Pull Request resolved: #1580
Extend the existing `mergeConfig` API so that it accepts functions as well as config objects.
These functions are provided with the leftward merged config as an argument, so that they may re-use or extend it in ways not covered by `mergeConfig`'s simple spread. For example:
# Example
Suppose `awesome-lib` exports `addThirdPartyMagic` for configuring Metro for some nice functionality, and it wants to merge intelligently with previous config:
```js
export function addThirdPartyMagic(baseConfig) {
return {
resolver: {
assetExts: [...baseConfig.resolver.assetExts, 'magic'],
},
};
}
```
## Currently
This would require a nest or sequence of `mergeConfig` calls with previous configs explicitly passed to `addThirdPartyMagic`, e.g:
```js
const {mergeConfig} = require('metro-config');
const {getDefaultValues} = require('react-native/metro-config');
const {addThirdPartyMagic} = require('awesome-lib');
const defaults = getDefaultValues(__dirname);
const myConfig = mergeConfig(defaults, {
resolver: {
assetExts: ['gif', ...defaults.resolver.assetExts],
},
})
module.exports = mergeConfig(myConfig, addThirdPartyMagic(myConfig));
```
There's a lot of boilerplate here, it's easy to get wrong and it doesn't get any nicer when you introduce a second and third library that wants to customise config.
## Proposed
Instead, by allowing functions that supply the the previous config, users can do:
```js
const {mergeConfig} = require('metro-config');
const {getDefaultValues} = require('react-native/metro-config');
const {addThirdPartyMagic} = require('awesome-lib');
module.exports = mergeConfig(getDefaultValues(__dirname), (baseConfig) => {
resolver: {
assetExts: ['gif', ...baseConfig.resolver.assetExts],
},
}, addThirdPartyMagic);
```
And this scales - every additional library is just another argument to `mergeConfig`.
### Future?
Out of scope for just now, but we *could* consider an array exported from `metro.config.js` to mean arguments to `mergeConfig`, and libraries like `react-native/metro-config` could export a (maybe async) function as a default export, so the future could look like this:
```ts
// metro.config.ts
import type {MetroConfig} from 'metro-config';
export default = [
import('react-native/metro-config'),
(defaults) => ({
resolver: {
sourceExts: [...defaults.resolver.sourceExts, 'custom']
}
}),
import('awesome-lib/metro-config'),
] satisfies MetroConfig[];
```
Reviewed By: huntie
Differential Revision: D82221532
fbshipit-source-id: ada49c39a2d5ec175eaa5c682b3ef851f0a03c0f
| `mergeConfig(...configs): MergedConfig` | Returns the merged configuration of two or more configuration objects or functions. |
732
+
733
+
`configs` may be any combination of configuration objects or functions (from Metro 0.83.2). Functions are called with the merged config of all configs to the left, which may be useful for complex merges with the previous config.
734
+
735
+
If any arguments are async functions, `mergeConfig` will return a `Promise`, otherwise it will return the merged config synchronously.
732
736
733
737
:::note
734
738
@@ -777,5 +781,12 @@ const configB = {
777
781
}
778
782
};
779
783
780
-
module.exports=mergeConfig(configA, configB);
784
+
// Function forms may be used to access the previous configuration
785
+
configCFn = (previousConfig /* result of mergeConfig(configA, configB) */) => {
0 commit comments