mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Community CLI: Don't clobber user config of Metro resolver/serializer, expose CLI config to user as defaults (#51836)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51836 Currently, `community-cli-plugin` loads the user config and then overrides parts of it - specifically `resolver.resolveRequest` and `serializer.getModulesRunBeforeMainModule`, making it impossible for a user to modify this config. Instead, treat the CLI's resolver and serializer customisations as "Framework defaults", layered on top of `react-native/metro-config` defaults but beneath a user's `metro.config.js`. This allows the user to obtain (via `react-native/metro-config`'s `getDefaultConfig`) and extend or override them, if they need to. This is technically breaking because users who currently have a custom `resolveRequest` or `getModulesRunBeforeMainModule` in their `metro.config.js` will have that config respected from this change, whereas currently they won't have any effect. Changelog: [General][Breaking] Community CLI users: user-defined `resolver.resolveRequest` and `serializer.getModulesRunBeforeMainModule` Metro config now takes precedence over CLI defaults Reviewed By: huntie Differential Revision: D74811395 fbshipit-source-id: c250caf798fdaedb0822bea3d6e65c0c3ae4d691
This commit is contained in:
committed by
Facebook GitHub Bot
parent
85498ad46f
commit
fe2bcbf4ba
@@ -35,7 +35,8 @@
|
||||
"metro-resolver": "^0.82.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/cli": "*"
|
||||
"@react-native-community/cli": "*",
|
||||
"@react-native/metro-config": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-community/cli": {
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {ConfigT, InputConfigT, YargArguments} from 'metro-config';
|
||||
|
||||
import {CLIError} from './errors';
|
||||
import {reactNativePlatformResolver} from './metroPlatformResolver';
|
||||
import {loadConfig, mergeConfig, resolveConfig} from 'metro-config';
|
||||
import {loadConfig, resolveConfig} from 'metro-config';
|
||||
import path from 'path';
|
||||
|
||||
const debug = require('debug')('ReactNative:CommunityCliPlugin');
|
||||
@@ -30,7 +30,7 @@ export type ConfigLoadingContext = $ReadOnly<{
|
||||
/**
|
||||
* Get the config options to override based on RN CLI inputs.
|
||||
*/
|
||||
function getOverrideConfig(
|
||||
function getCommunityCliDefaultConfig(
|
||||
ctx: ConfigLoadingContext,
|
||||
config: ConfigT,
|
||||
): InputConfigT {
|
||||
@@ -85,6 +85,31 @@ export default async function loadMetroConfig(
|
||||
ctx: ConfigLoadingContext,
|
||||
options: YargArguments = {},
|
||||
): Promise<ConfigT> {
|
||||
let RNMetroConfig = null;
|
||||
try {
|
||||
RNMetroConfig = require('@react-native/metro-config');
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
"Cannot resolve `@react-native/metro-config`. Ensure it is listed in your project's `devDependencies`.",
|
||||
);
|
||||
}
|
||||
|
||||
// Get the RN defaults before our customisations
|
||||
const defaultConfig = RNMetroConfig.getDefaultConfig(ctx.root);
|
||||
// Unflag the config as being loaded - it must be loaded again in userland.
|
||||
global.__REACT_NATIVE_METRO_CONFIG_LOADED = false;
|
||||
|
||||
// Add our defaults to `@react-native/metro-config` before the user config
|
||||
// loads them.
|
||||
if (typeof RNMetroConfig.setFrameworkDefaults !== 'function') {
|
||||
throw new Error(
|
||||
'`@react-native/metro-config` does not have the expected API. Ensure it matches your React Native version.',
|
||||
);
|
||||
}
|
||||
RNMetroConfig.setFrameworkDefaults(
|
||||
getCommunityCliDefaultConfig(ctx, defaultConfig),
|
||||
);
|
||||
|
||||
const cwd = ctx.root;
|
||||
const projectConfig = await resolveConfig(options.config, cwd);
|
||||
|
||||
@@ -108,13 +133,8 @@ This warning will be removed in future (https://github.com/facebook/metro/issues
|
||||
console.warn(line);
|
||||
}
|
||||
}
|
||||
|
||||
const config = await loadConfig({
|
||||
return loadConfig({
|
||||
cwd,
|
||||
...options,
|
||||
});
|
||||
|
||||
const overrideConfig = getOverrideConfig(ctx, config);
|
||||
|
||||
return mergeConfig(config, overrideConfig);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {ConfigT} from 'metro-config';
|
||||
import type {ConfigT, InputConfigT} from 'metro-config';
|
||||
|
||||
import {getDefaultConfig as getBaseConfig, mergeConfig} from 'metro-config';
|
||||
|
||||
@@ -43,11 +43,16 @@ const INTERNAL_CALLSITES_REGEX = new RegExp(
|
||||
|
||||
export {mergeConfig} from 'metro-config';
|
||||
|
||||
let frameworkDefaults = {};
|
||||
export function setFrameworkDefaults(config: InputConfigT) {
|
||||
frameworkDefaults = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base Metro configuration for a React Native project.
|
||||
*/
|
||||
export function getDefaultConfig(projectRoot: string): ConfigT {
|
||||
const config = {
|
||||
const reactNativeDefaults = {
|
||||
resolver: {
|
||||
resolverMainFields: ['react-native', 'browser', 'main'],
|
||||
platforms: ['android', 'ios'],
|
||||
@@ -99,5 +104,7 @@ export function getDefaultConfig(projectRoot: string): ConfigT {
|
||||
// Set global hook so that the CLI can detect when this config has been loaded
|
||||
global.__REACT_NATIVE_METRO_CONFIG_LOADED = true;
|
||||
|
||||
return mergeConfig(getBaseConfig.getDefaultValues(projectRoot), config);
|
||||
const metroDefaults = getBaseConfig.getDefaultValues(projectRoot);
|
||||
|
||||
return mergeConfig(metroDefaults, reactNativeDefaults, frameworkDefaults);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user