Skip to content

Commit

Permalink
[RFC] feat: Update cli-plugin-metro to use defaults in app metro.conf…
Browse files Browse the repository at this point in the history
…ig.js from RN 0.72
  • Loading branch information
huntie committed Mar 16, 2023
1 parent 28fe385 commit 598f1a0
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 35 deletions.
2 changes: 1 addition & 1 deletion packages/cli-plugin-metro/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export type {MetroConfig} from 'metro-config';
export {
Config,
ConfigLoadingContext,
getDefaultConfig,
getDefaultConfigPre72 as getDefaultConfig,
default as loadMetroConfig,
} from './tools/loadMetroConfig';
export {
Expand Down
104 changes: 70 additions & 34 deletions packages/cli-plugin-metro/src/tools/loadMetroConfig.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/**
* Configuration file of Metro.
*/
import path from 'path';
import {ConfigT, InputConfigT, loadConfig} from 'metro-config';
import {ConfigT, InputConfigT, loadConfig, mergeConfig} from 'metro-config';
import type {Config} from '@react-native-community/cli-types';
import {reactNativePlatformResolver} from './metroPlatformResolver';

/**
* @deprecated (React Native 0.72.0) Please use
* https://github.com/facebook/react-native/tree/main/package/metro-config/index.js
*/
const INTERNAL_CALLSITES_REGEX = new RegExp(
[
'/Libraries/Renderer/implementations/.+\\.js$',
Expand Down Expand Up @@ -35,14 +36,60 @@ export type ConfigLoadingContext = Pick<

/**
* Default configuration
*
* @deprecated (React Native 0.72.0) Please use
* https://github.com/facebook/react-native/tree/main/package/metro-config/index.js
*/
export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => {
export const getDefaultConfigPre72 = (
ctx: ConfigLoadingContext,
): InputConfigT => {
const defaultConfig = {
resolver: {
resolverMainFields: ['react-native', 'browser', 'main'],
unstable_conditionNames: ['import', 'require', 'react-native'],
},
serializer: {
getPolyfills: () =>
require(path.join(ctx.reactNativePath, 'rn-get-polyfills'))(),
},
server: {
port: Number(process.env.RCT_METRO_PORT) || 8081,
},
symbolicator: {
customizeFrame: (frame: {file?: string}) => {
const collapse = Boolean(
frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file),
);
return {collapse};
},
},
transformer: {
allowOptionalDependencies: true,
babelTransformerPath: require.resolve(
'metro-react-native-babel-transformer',
),
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
asyncRequireModulePath: require.resolve(
'metro-runtime/src/modules/asyncRequire',
),
},
watchFolders: [],
};

return mergeConfig(defaultConfig, getOverrideConfig(ctx));
};

/**
* Get the config options to override based on RN CLI inputs.
*/
function getOverrideConfig(ctx: ConfigLoadingContext): InputConfigT {
const outOfTreePlatforms = Object.keys(ctx.platforms).filter(
(platform) => ctx.platforms[platform].npmPackageName,
);

return {
resolver: {
platforms: [...Object.keys(ctx.platforms), 'native'],
resolveRequest:
outOfTreePlatforms.length === 0
? undefined
Expand All @@ -55,9 +102,6 @@ export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => {
{},
),
),
resolverMainFields: ['react-native', 'browser', 'main'],
platforms: [...Object.keys(ctx.platforms), 'native'],
unstable_conditionNames: ['import', 'require', 'react-native'],
},
serializer: {
// We can include multiple copies of InitializeCore here because metro will
Expand All @@ -76,30 +120,8 @@ export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => {
getPolyfills: () =>
require(path.join(ctx.reactNativePath, 'rn-get-polyfills'))(),
},
server: {
port: Number(process.env.RCT_METRO_PORT) || 8081,
},
symbolicator: {
customizeFrame: (frame) => {
const collapse = Boolean(
frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file),
);
return {collapse};
},
},
transformer: {
allowOptionalDependencies: true,
babelTransformerPath: require.resolve(
'metro-react-native-babel-transformer',
),
assetRegistryPath: 'react-native/Libraries/Image/AssetRegistry',
asyncRequireModulePath: require.resolve(
'metro-runtime/src/modules/asyncRequire',
),
},
watchFolders: [],
};
};
}

export interface ConfigOptionsT {
maxWorkers?: number;
Expand All @@ -113,15 +135,29 @@ export interface ConfigOptionsT {
}

/**
* Loads Metro Config and applies `options` on top of the resolved config.
* Load Metro config.
*
* This allows the CLI to always overwrite the file settings.
* Allows the CLI to override certain defaults in the base `metro.config.js`
* based on dynamic user options in `ctx`.
*/
export default function loadMetroConfig(
ctx: ConfigLoadingContext,
options?: ConfigOptionsT,
): Promise<ConfigT> {
const defaultConfig = {...getDefaultConfig(ctx)};
const reactNativeVersion = require(ctx.reactNativePath + '/package.json')
?.version;

if (
reactNativeVersion &&
parseInt(reactNativeVersion.split('.')[0], 10) >= 72
) {
// React Native 0.72 and later: Load Metro config which inherits
// @react-native/metro-config, and apply sparse additional config
return loadConfig({cwd: ctx.root}, getOverrideConfig(ctx));
}

// Pre React Native 0.72: Load Metro config and apply all legacy defaults
const defaultConfig = {...getDefaultConfigPre72(ctx)};
if (options && options.reporter) {
defaultConfig.reporter = options.reporter;
}
Expand Down

0 comments on commit 598f1a0

Please sign in to comment.