1- /**
2- * Configuration file of Metro.
3- */
41import path from 'path' ;
5- import { ConfigT , InputConfigT , loadConfig } from 'metro-config' ;
2+ import { ConfigT , InputConfigT , loadConfig , mergeConfig } from 'metro-config' ;
63import type { Config } from '@react-native-community/cli-types' ;
74import { reactNativePlatformResolver } from './metroPlatformResolver' ;
85
6+ /**
7+ * @deprecated (React Native 0.72.0) Please use
8+ * https://github.com/facebook/react-native/tree/main/package/metro-config/index.js
9+ */
910const INTERNAL_CALLSITES_REGEX = new RegExp (
1011 [
1112 '/Libraries/Renderer/implementations/.+\\.js$' ,
@@ -35,14 +36,60 @@ export type ConfigLoadingContext = Pick<
3536
3637/**
3738 * Default configuration
39+ *
40+ * @deprecated (React Native 0.72.0) Please use
41+ * https://github.com/facebook/react-native/tree/main/package/metro-config/index.js
3842 */
39- export const getDefaultConfig = ( ctx : ConfigLoadingContext ) : InputConfigT => {
43+ export const getDefaultConfigPre72 = (
44+ ctx : ConfigLoadingContext ,
45+ ) : InputConfigT => {
46+ const defaultConfig = {
47+ resolver : {
48+ resolverMainFields : [ 'react-native' , 'browser' , 'main' ] ,
49+ unstable_conditionNames : [ 'import' , 'require' , 'react-native' ] ,
50+ } ,
51+ serializer : {
52+ getPolyfills : ( ) =>
53+ require ( path . join ( ctx . reactNativePath , 'rn-get-polyfills' ) ) ( ) ,
54+ } ,
55+ server : {
56+ port : Number ( process . env . RCT_METRO_PORT ) || 8081 ,
57+ } ,
58+ symbolicator : {
59+ customizeFrame : ( frame : { file ?: string } ) => {
60+ const collapse = Boolean (
61+ frame . file && INTERNAL_CALLSITES_REGEX . test ( frame . file ) ,
62+ ) ;
63+ return { collapse} ;
64+ } ,
65+ } ,
66+ transformer : {
67+ allowOptionalDependencies : true ,
68+ babelTransformerPath : require . resolve (
69+ 'metro-react-native-babel-transformer' ,
70+ ) ,
71+ assetRegistryPath : 'react-native/Libraries/Image/AssetRegistry' ,
72+ asyncRequireModulePath : require . resolve (
73+ 'metro-runtime/src/modules/asyncRequire' ,
74+ ) ,
75+ } ,
76+ watchFolders : [ ] ,
77+ } ;
78+
79+ return mergeConfig ( defaultConfig , getOverrideConfig ( ctx ) ) ;
80+ } ;
81+
82+ /**
83+ * Get the config options to override based on RN CLI inputs.
84+ */
85+ function getOverrideConfig ( ctx : ConfigLoadingContext ) : InputConfigT {
4086 const outOfTreePlatforms = Object . keys ( ctx . platforms ) . filter (
4187 ( platform ) => ctx . platforms [ platform ] . npmPackageName ,
4288 ) ;
4389
4490 return {
4591 resolver : {
92+ platforms : [ ...Object . keys ( ctx . platforms ) , 'native' ] ,
4693 resolveRequest :
4794 outOfTreePlatforms . length === 0
4895 ? undefined
@@ -55,9 +102,6 @@ export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => {
55102 { } ,
56103 ) ,
57104 ) ,
58- resolverMainFields : [ 'react-native' , 'browser' , 'main' ] ,
59- platforms : [ ...Object . keys ( ctx . platforms ) , 'native' ] ,
60- unstable_conditionNames : [ 'import' , 'require' , 'react-native' ] ,
61105 } ,
62106 serializer : {
63107 // We can include multiple copies of InitializeCore here because metro will
@@ -76,30 +120,8 @@ export const getDefaultConfig = (ctx: ConfigLoadingContext): InputConfigT => {
76120 getPolyfills : ( ) =>
77121 require ( path . join ( ctx . reactNativePath , 'rn-get-polyfills' ) ) ( ) ,
78122 } ,
79- server : {
80- port : Number ( process . env . RCT_METRO_PORT ) || 8081 ,
81- } ,
82- symbolicator : {
83- customizeFrame : ( frame ) => {
84- const collapse = Boolean (
85- frame . file && INTERNAL_CALLSITES_REGEX . test ( frame . file ) ,
86- ) ;
87- return { collapse} ;
88- } ,
89- } ,
90- transformer : {
91- allowOptionalDependencies : true ,
92- babelTransformerPath : require . resolve (
93- 'metro-react-native-babel-transformer' ,
94- ) ,
95- assetRegistryPath : 'react-native/Libraries/Image/AssetRegistry' ,
96- asyncRequireModulePath : require . resolve (
97- 'metro-runtime/src/modules/asyncRequire' ,
98- ) ,
99- } ,
100- watchFolders : [ ] ,
101123 } ;
102- } ;
124+ }
103125
104126export interface ConfigOptionsT {
105127 maxWorkers ?: number ;
@@ -113,15 +135,29 @@ export interface ConfigOptionsT {
113135}
114136
115137/**
116- * Loads Metro Config and applies `options` on top of the resolved config.
138+ * Load Metro config.
117139 *
118- * This allows the CLI to always overwrite the file settings.
140+ * Allows the CLI to override certain defaults in the base `metro.config.js`
141+ * based on dynamic user options in `ctx`.
119142 */
120143export default function loadMetroConfig (
121144 ctx : ConfigLoadingContext ,
122145 options ?: ConfigOptionsT ,
123146) : Promise < ConfigT > {
124- const defaultConfig = { ...getDefaultConfig ( ctx ) } ;
147+ const reactNativeVersion = require ( ctx . reactNativePath + '/package.json' )
148+ ?. version ;
149+
150+ if (
151+ reactNativeVersion &&
152+ parseInt ( reactNativeVersion . split ( '.' ) [ 0 ] , 10 ) >= 72
153+ ) {
154+ // React Native 0.72 and later: Load Metro config which inherits
155+ // @react -native/metro-config, and apply sparse additional config
156+ return loadConfig ( { cwd : ctx . root } , getOverrideConfig ( ctx ) ) ;
157+ }
158+
159+ // Pre React Native 0.72: Load Metro config and apply all legacy defaults
160+ const defaultConfig = { ...getDefaultConfigPre72 ( ctx ) } ;
125161 if ( options && options . reporter ) {
126162 defaultConfig . reporter = options . reporter ;
127163 }
0 commit comments