Essential React Native Configuration Files for Understanding the Architecture

The most important React Native configuration files include react-native.config.js for CLI commands, metro.config.js for bundling, ReactNativeFeatureFlags.config.js for architectural toggles, and scripts/build/config.js for the monorepo build pipeline.

React Native is a complex monorepo that stitches together JavaScript tooling, native bridges, and platform-specific build systems. Understanding the React Native configuration files scattered throughout the repository is essential for grasping how the framework bundles code, executes native modules, and toggles major architectural features like Fabric and TurboModules.

CLI and Entry Point Configuration

The command-line interface serves as the primary entry point for developers interacting with React Native. The configuration files in this layer define how commands are registered and how the CLI discovers platform-specific project files.

react-native.config.js

Located at packages/react-native/react-native.config.js, this file configures the React Native CLI itself, defining how commands are registered and how the CLI discovers Android and iOS project files. It integrates with @react-native-community/cli-platform-android and @react-native-community/cli-platform-ios to discover native projects and exposes custom commands such as codegen.

This file matters for architecture understanding because it shows exactly how the JavaScript tooling hooks into the Android and Xcode build systems. It defines the integration points where the CLI hands off to Gradle or xcodebuild.

Bundling and Transformation Pipeline

Before JavaScript reaches the device, it passes through a bundler and transpiler. These configuration files control how source code is resolved, transformed, and optimized.

metro.config.js

The packages/react-native/metro.config.js file configures the Metro bundler settings, including watch folders, resolver block-lists, and node-module resolution. Metro determines how JavaScript source is located, bundled, and transformed before it reaches the native runtime.

Customizing Metro changes the bundle’s dependency graph. For example, adding a watch folder injects platform-specific code or local libraries into the app.

// packages/react-native/metro.config.js
const {mergeConfig} = require('metro-config');
const {getDefaultConfig} = require('@react-native/metro-config');
const path = require('path');

const config = {
  watchFolders: [
    // Existing folders …
    path.resolve(__dirname, '../../my-extra-modules'), // ← add your folder here
  ],
  resolver: {
    blockList: [/buck-out/, /sdks\/hermes/],
    extraNodeModules: {
      'react-native': __dirname,
    },
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

.babelrc

The .babelrc files (root and package-specific) define Babel presets and plugins such as @babel/preset-flow, @babel/preset-env, and babel-plugin-minify-dead-code-elimination. These control the JavaScript transpilation pipeline that produces code executed by the JavaScript engine (Hermes or V8) on the device.

Every JavaScript file that Metro bundles passes through this transpilation pipeline, so the Babel configuration directly determines which language features (such as optional chaining or Flow types) are supported in the runtime bundle.

// .babelrc (root)
{
  "presets": [
    "@babel/preset-flow",
    ["@babel/preset-env", { "targets": { "node": "18" } }]
  ],
  "plugins": [
    "babel-plugin-syntax-hermes-parser",
    [
      "babel-plugin-transform-define",
      { "process.env.BUILD_EXCLUDE_BABEL_REGISTER": true }
    ],
    // New plugin – optional chaining support
    "@babel/plugin-proposal-optional-chaining"
  ]
}

Build System and Type Generation

React Native’s monorepo requires orchestrated builds for native modules and type definitions. These configuration files drive the compilation process.

scripts/build/config.js

The scripts/build/config.js file defines monorepo-wide build options, including which packages are built and Flow/TypeScript generation flags. This drives the yarn build process that compiles native modules and generates type definitions, affecting both JavaScript and native sides.

scripts/js-api/config.js

Located at scripts/js-api/config.js, this file serves as the type-generation entry point, referencing packages/react-native/index.js.flow and defining output directories. It influences the generated TypeScript/Flow typings that describe the bridge API surface.

Architectural Feature Flags

Modern React Native uses feature flags to toggle entire subsystems without code changes. This configuration file is the master switchboard.

ReactNativeFeatureFlags.config.js

The packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js file contains the declarative list of feature flags such as enableFabricRenderer, enableBridgelessArchitecture, and useTurboModules. These flags are the primary mechanism for toggling whole architectural subsystems, gating Fabric, TurboModules, network inspection, and Bridgeless mode.

Changing a flag can flip the runtime architecture without touching core code.


# Run the CLI with a custom feature‑flag override

yarn react-native start --config=./react-native.config.js \
  --reset-cache --activeArch=android \
  --enableFeature=enableFabricRenderer

The CLI reads ReactNativeFeatureFlags.config.js, merges the override, and the native runtime starts with Fabric enabled.

Testing and Type Safety

Configuration files for testing and type checking ensure the JavaScript codebase remains robust and mirrors the production runtime.

jest.config.js

The root jest.config.js configures the Jest test runner, including transform settings, coverage, and setup files. It mirrors the Babel/Metro pipeline in a Node environment, making it easier to reason about how tests simulate the real runtime.

// jest.config.js (root)
module.exports = {
  preset: 'react-native',
  setupFiles: ['./jest/setup.js'],
  transform: {
    '^.+\\.[jt]sx?$': 'babel-jest',
  },
  globals: {
    __REACT_NATIVE_FEATURE_FLAGS__: {
      enableBridgelessArchitecture: true,
    },
  },
};

This configuration lets Jest run with the same feature flag state the app would have in a Bridgeless build, verifying compatibility.

tsconfig.json

The packages/react-native/tsconfig.json file defines TypeScript compiler options for the core package. It shows how the core codebase is type-checked and which parts of the API are exposed to TypeScript consumers.

Workspace Orchestration

At the root level, the workspace configuration ties together all subsystems and tooling versions.

package.json

The root package.json defines the workspace layout, npm scripts, and devDependencies (Babel, Metro, TypeScript, Jest, etc.). It provides a high-level map of the repo’s modules, the tooling versions that power the build and test pipelines, and the scripts that launch the architecture (e.g., yarn start, yarn build).

Summary

Understanding React Native’s architecture requires studying how its configuration files wire together JavaScript tooling, native bridges, and feature flags. Key takeaways include:

Frequently Asked Questions

What is the difference between metro.config.js and react-native.config.js?

react-native.config.js configures the React Native CLI itself, defining how commands are registered and how the CLI discovers Android and iOS project files. metro.config.js specifically configures the Metro bundler, controlling how JavaScript files are resolved, watched, and transformed. While the CLI config orchestrates the development workflow, the Metro config directly impacts the bundle contents and build performance.

How do feature flags in ReactNativeFeatureFlags.config.js affect the architecture?

The ReactNativeFeatureFlags.config.js file contains declarative switches such as enableFabricRenderer, enableBridgelessArchitecture, and useTurboModules. These flags are the primary mechanism for toggling whole architectural subsystems without code changes; toggling a flag can switch the runtime from the legacy bridge to the new Bridgeless architecture or enable the Fabric renderer. This configuration file serves as the central mechanism for rolling out and testing major architectural changes across the framework.

Why is .babelrc important for React Native's JavaScript transformation?

The .babelrc files define the Babel presets and plugins that transpile modern JavaScript and Flow code into a format compatible with the Hermes or V8 engines running on mobile devices. Every JavaScript file that Metro bundles passes through this transpilation pipeline, so the Babel configuration directly determines which language features (such as optional chaining or Flow types) are supported in the runtime bundle. Modifying .babelrc changes the fundamental compatibility and capabilities of the generated JavaScript code.

Where are TypeScript definitions generated in the React Native monorepo?

TypeScript and Flow definitions are generated via scripts/js-api/config.js, which serves as the entry point for type generation, referencing packages/react-native/index.js.flow and defining output directories. The scripts/build/config.js file complements this by orchestrating the broader monorepo build process that compiles native modules and generates type definitions. Together, these configuration files ensure that the bridge API surface is properly typed for both JavaScript and TypeScript consumers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →