# Create React App — Administrator & Developer Guide

Create React App (CRA) is a Lerna monorepo providing a zero-configuration toolchain for bootstrapping and developing React applications. This guide covers the full internal architecture, every configuration surface, the build pipeline, testing infrastructure, and operational concerns for administrators, contributors, and developers who maintain or extend CRA-based projects.

For installation walkthroughs, everyday usage, and feature tutorials, see the [User Guide](/guides/facebook/create-react-app/user-guide/).

> [!IMPORTANT]
> Create React App is officially deprecated as of the latest source. The CLI `init()` function displays a deprecation warning, and the Docusaurus website metadata states "Create React App is deprecated." This guide remains valuable for the thousands of production applications still running on CRA, and for understanding the architectural decisions that influenced the React ecosystem.

---

## 1. Architecture Overview

### 1.1 Monorepo Structure

CRA uses Lerna with npm workspaces. The top-level `lerna.json` declares the package locations, and `package.json` configures workspaces:

```
create-react-app/
├── packages/
│   ├── create-react-app/          # CLI scaffolder (5.1.0)
│   ├── react-scripts/             # Build toolchain (5.1.0)
│   ├── react-dev-utils/           # 33 shared utility modules (12.1.0)
│   ├── react-error-overlay/       # Browser error overlay (6.1.0)
│   ├── babel-preset-react-app/    # Babel preset (10.1.0)
│   ├── babel-plugin-named-asset-import/  # SVG named imports (0.4.0)
│   ├── eslint-config-react-app/   # ESLint configuration (7.1.0)
│   ├── confusing-browser-globals/ # Restricted globals list (1.0.11)
│   ├── react-app-polyfill/        # IE9/IE11/jsdom/stable polyfills (3.0.0)
│   ├── cra-template/              # Default JS template (1.3.0)
│   └── cra-template-typescript/   # TypeScript template (1.3.0)
├── docusaurus/
│   └── website/                   # Documentation site
└── test/                          # E2E integration tests
```

### 1.2 Package Dependency Graph

The packages form a layered dependency tree:

```
create-react-app (CLI)
  └── spawns npx react-scripts init

react-scripts (build toolchain)
  ├── babel-preset-react-app
  │   └── babel-plugin-named-asset-import
  ├── eslint-config-react-app
  │   └── confusing-browser-globals
  ├── react-dev-utils (33 modules)
  │   └── react-error-overlay
  └── react-app-polyfill (via templates)

cra-template / cra-template-typescript
  └── consumed by create-react-app during scaffolding
```

### 1.3 Design Principles

1. **Zero configuration** — `react-scripts` encapsulates all tooling config so end users never touch webpack, Babel, or ESLint directly.
2. **Single dependency** — A generated project depends only on `react-scripts` (plus React itself). All build tools are transitive dependencies.
3. **Eject escape hatch** — Running `react-scripts eject` copies all configuration and scripts into the project, removing the `react-scripts` dependency permanently.
4. **Convention over configuration** — Fixed directory structure (`src/`, `public/`, `build/`), fixed entry points (`src/index.js`, `public/index.html`), environment variable prefix (`REACT_APP_*`).

> [!NOTE]
> The "single dependency" model means that upgrading `react-scripts` upgrades webpack, Babel, ESLint, Jest, PostCSS, and every other tool simultaneously. This is both the primary strength (simplicity) and primary pain point (version lock-in) of the architecture.

---

## 2. System Requirements

### 2.1 Runtime Requirements

| Requirement | Minimum | Recommended |
|---|---|---|
| Node.js | 14.0.0 | 18.x LTS or 20.x LTS |
| npm | 6.x | 8.x+ |
| Yarn (optional) | 1.x | 1.22+ |
| pnpm (optional) | 6.x | 8.x+ |
| Disk space | 200 MB (node_modules) | 500 MB+ (with cache) |
| RAM | 1 GB free | 4 GB+ (large projects) |

### 2.2 Node.js Version Constraints

The CLI (`create-react-app/index.js`) enforces a minimum Node version check at startup. The `engines` field in `react-scripts/package.json` specifies the supported range.

```json
{
  "engines": {
    "node": ">=14"
  }
}
```

> [!WARNING]
> Node.js 17+ changed the default OpenSSL provider, causing `ERR_OSSL_EVP_UNSUPPORTED` errors with webpack's hash functions. The workaround is setting `NODE_OPTIONS=--openssl-legacy-provider` before running build commands. This is a frequently reported issue (GitHub #17216).

### 2.3 Browser Support

Default browserslist configuration in generated projects:

```json
{
  "browserslist": {
    "production": [">0.2%", "not dead", "not op_mini all"],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
```

The `react-app-polyfill` package provides targeted polyfills:

| Import | Target |
|---|---|
| `react-app-polyfill/ie9` | IE9+ (includes IE11 polyfills) |
| `react-app-polyfill/ie11` | IE11+ |
| `react-app-polyfill/stable` | All stable JS features |
| `react-app-polyfill/jsdom` | jsdom test environment |

---

## 3. Configuration Reference

### 3.1 Environment Variables — Complete Reference

CRA uses environment variables as its primary configuration mechanism. Variables are loaded from `.env` files by `config/env.js` using `dotenv` and `dotenv-expand`.

#### .env File Loading Order

Files are loaded in this exact precedence (highest priority first):

```
.env.{NODE_ENV}.local    # e.g., .env.development.local
.env.local               # NOT loaded in test environment
.env.{NODE_ENV}          # e.g., .env.development
.env                     # Base defaults
```

All `REACT_APP_*` prefixed variables are injected into the client bundle via webpack's `DefinePlugin` as `process.env.REACT_APP_*`.

#### Build System Variables

| Variable | Default | Used In | Description |
|---|---|---|---|
| `NODE_ENV` | `development` | env.js, webpack | Build mode: `development`, `production`, or `test` |
| `BABEL_ENV` | same as NODE_ENV | env.js | Babel environment (set to match NODE_ENV) |
| `PUBLIC_URL` | `/` | paths.js, webpack | Base URL for the application (maps to `homepage` in package.json) |
| `BUILD_PATH` | `build` | paths.js | Output directory for production builds |
| `GENERATE_SOURCEMAP` | `true` | webpack.config.js | Set to `false` to skip production source maps |
| `INLINE_RUNTIME_CHUNK` | `true` | webpack.config.js | Set to `false` to not inline the webpack runtime chunk |
| `IMAGE_INLINE_SIZE_LIMIT` | `10000` | webpack.config.js | Max bytes for inlining images as data URIs |
| `FAST_REFRESH` | `true` | webpack.config.js | Enable React Fast Refresh in development |
| `TSC_COMPILE_ON_ERROR` | `false` | webpack.config.js | Allow builds with TypeScript errors |
| `DISABLE_ESLINT_PLUGIN` | `false` | webpack.config.js | Completely disable ESLint during builds |
| `ESLINT_NO_DEV_ERRORS` | `false` | eslintFormatter.js | Downgrade ESLint errors to warnings in dev |
| `DISABLE_NEW_JSX_TRANSFORM` | `false` | babel-preset-react-app | Use classic `React.createElement` instead of automatic JSX transform |

#### Development Server Variables

| Variable | Default | Used In | Description |
|---|---|---|---|
| `HOST` | `0.0.0.0` | start.js, webpackDevServer.config.js | Dev server bind address |
| `PORT` | `3000` | start.js | Dev server port (auto-increments if occupied) |
| `HTTPS` | `false` | start.js | Enable HTTPS for dev server |
| `SSL_CRT_FILE` | none | getHttpsConfig.js | Path to custom SSL certificate file |
| `SSL_KEY_FILE` | none | getHttpsConfig.js | Path to custom SSL key file |
| `DANGEROUSLY_DISABLE_HOST_CHECK` | `false` | webpackDevServer.config.js | Disable host header validation |
| `WDS_SOCKET_HOST` | `window.location.hostname` | webpackHotDevClient.js | WebSocket host for HMR |
| `WDS_SOCKET_PATH` | `/ws` | webpackHotDevClient.js | WebSocket path for HMR |
| `WDS_SOCKET_PORT` | `window.location.port` | webpackHotDevClient.js | WebSocket port for HMR |
| `BROWSER` | system default | openBrowser.js | Browser to open (name, path, or `none`) |
| `BROWSER_ARGS` | none | openBrowser.js | Arguments passed to the browser process |

#### Editor Integration Variables

| Variable | Default | Used In | Description |
|---|---|---|---|
| `REACT_EDITOR` | falls through | launchEditor.js | Editor for click-to-source (highest priority) |
| `VISUAL` | falls through | launchEditor.js | Editor fallback (second priority) |
| `EDITOR` | falls through | launchEditor.js | Editor fallback (third priority) |

#### CI/Test Variables

| Variable | Default | Used In | Description |
|---|---|---|---|
| `CI` | `false` | build.js, test.js | Treat warnings as errors in build; run tests non-interactively |
| `SKIP_PREFLIGHT_CHECK` | `false` | react-scripts bin | Skip the babel/webpack/jest version conflict check |

> [!TIP]
> When deploying to CI, set `CI=true` to make the build fail on any ESLint warning. This catches issues that would be silently ignored in local development. The test runner also changes behavior: it runs all tests once and exits instead of entering watch mode.

### 3.2 package.json Configuration

CRA reads several fields from the project's `package.json`:

| Field | Purpose |
|---|---|
| `homepage` | Sets `PUBLIC_URL` for asset paths (e.g., `"https://myapp.com/subdir"`) |
| `proxy` | Single-origin API proxy for development (e.g., `"http://localhost:4000"`) |
| `browserslist` | Target browsers for Babel and PostCSS Autoprefixer |
| `eslintConfig` | ESLint configuration (extends `react-app` by default) |
| `jest` | Jest overrides (limited — see Section 8.4) |

### 3.3 Advanced Proxy Configuration

For multi-target proxying, create `src/setupProxy.js`:

```javascript
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:5000',
      changeOrigin: true,
    })
  );
};
```

This file is loaded by the dev server automatically. It receives the Express app instance and can register any middleware.

### 3.4 TypeScript Configuration

When `tsconfig.json` is present, `config/modules.js` reads it to configure:

- **baseUrl** — Creates webpack `resolve.modules` entry and Jest `moduleDirectories`
- **paths** — Maps to webpack `resolve.alias` entries and Jest `moduleNameMapper`

The TypeScript compiler itself runs via `ForkTsCheckerWebpackPlugin` in a separate process. Type errors are reported but do not block compilation unless `TSC_COMPILE_ON_ERROR` is `false` (the default).

```json
{
  "compilerOptions": {
    "baseUrl": "src",
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  }
}
```

> [!NOTE]
> CRA overwrites certain `tsconfig.json` fields on startup. Fields like `module`, `moduleResolution`, `isolatedModules`, and `jsx` are forced to values compatible with the webpack pipeline. The rewrite is logged to the console.

### 3.5 Path Resolution

`config/paths.js` resolves all project paths from the app root. The resolved paths object:

| Key | Default Path | Description |
|---|---|---|
| `dotenv` | `.env` | Base environment file |
| `appPath` | `.` | Project root |
| `appBuild` | `build` (or BUILD_PATH) | Production output |
| `appPublic` | `public` | Static assets |
| `appHtml` | `public/index.html` | HTML template |
| `appIndexJs` | `src/index.{js,jsx,ts,tsx}` | Application entry point |
| `appPackageJson` | `package.json` | Project manifest |
| `appSrc` | `src` | Source directory |
| `appTsConfig` | `tsconfig.json` | TypeScript config |
| `appJsConfig` | `jsconfig.json` | JavaScript config |
| `yarnLockFile` | `yarn.lock` | Yarn lockfile |
| `testsSetup` | `src/setupTests.{js,ts}` | Jest setup file |
| `proxySetup` | `src/setupProxy.js` | Dev proxy config |
| `appNodeModules` | `node_modules` | Dependencies |
| `appWebpackCache` | `node_modules/.cache` | Webpack persistent cache |
| `appTsBuildInfoFile` | `node_modules/.cache/tsconfig.tsbuildinfo` | TS incremental build |
| `swSrc` | `src/service-worker.{js,ts}` | Service worker source |

Module file extensions searched in order:

```javascript
const moduleFileExtensions = [
  'web.mjs', 'mjs', 'web.js', 'js',
  'web.ts', 'ts', 'web.tsx', 'tsx',
  'json', 'web.jsx', 'jsx',
];
```

---

## 4. Deployment & Scaling

### 4.1 Production Build Pipeline

Running `react-scripts build` (`scripts/build.js`) executes this sequence:

1. Sets `NODE_ENV=production` and `BABEL_ENV=production`
2. Loads `.env` files via `config/env.js`
3. Verifies `public/index.html` and `src/index.js` exist (`checkRequiredFiles`)
4. Measures existing build sizes for diff reporting (`FileSizeReporter`)
5. Cleans the `BUILD_PATH` directory
6. Copies `public/` to build output (excluding `index.html`)
7. Runs webpack with production configuration
8. Reports gzipped file sizes with before/after comparison
9. Prints hosting instructions (`printHostingInstructions`)

The production webpack configuration enables:

- **Code splitting** — Dynamic `import()` creates separate chunks
- **Tree shaking** — Unused exports eliminated via webpack's module concatenation
- **Minification** — TerserPlugin (JS, targeting ECMAScript 5 output) and CssMinimizerPlugin (CSS)
- **Asset hashing** — Content hashes in filenames for cache busting (`[name].[contenthash:8].js`)
- **Chunk optimization** — `splitChunks.chunks: 'all'` with `runtimeChunk: true`
- **Source maps** — Generated unless `GENERATE_SOURCEMAP=false`

### 4.2 Build Output Structure

```
build/
├── static/
│   ├── js/
│   │   ├── main.[hash].js          # Application code
│   │   ├── main.[hash].js.map      # Source map
│   │   ├── [id].[hash].chunk.js    # Split chunks
│   │   └── runtime-main.[hash].js  # Webpack runtime (or inlined)
│   ├── css/
│   │   ├── main.[hash].css         # Extracted CSS
│   │   └── main.[hash].css.map     # CSS source map
│   └── media/
│       └── [name].[hash].[ext]     # Images, fonts, other assets
├── index.html                       # Processed HTML with injected assets
├── asset-manifest.json              # Map of logical names to hashed paths
├── manifest.json                    # PWA web app manifest (from public/)
└── service-worker.js                # Generated by WorkboxWebpackPlugin (if src/service-worker.js exists)
```

### 4.3 Deployment Targets

The `printHostingInstructions.js` utility detects the deployment target from `package.json` and prints context-specific instructions.

#### Static File Server

```bash
npm install -g serve
serve -s build
```

The `-s` flag enables single-page app mode (rewrites all routes to `index.html`).

#### Subpath Deployment

Set `homepage` in `package.json` to configure the base URL:

```json
{
  "homepage": "https://example.com/my-app"
}
```

This sets `PUBLIC_URL` to `/my-app`, ensuring all asset paths are correctly prefixed. The `%PUBLIC_URL%` placeholder in `public/index.html` is replaced at build time by `InterpolateHtmlPlugin`.

#### CDN / Custom Build Directory

```bash
BUILD_PATH=dist react-scripts build
```

> [!TIP]
> For GitHub Pages deployment, set `"homepage": "https://username.github.io/repo-name"`. For relative paths (useful when the deployment path is unknown at build time), set `"homepage": "."` — this makes all asset references relative.

### 4.4 Service Worker (PWA)

CRA supports Progressive Web App features via Workbox. When `src/service-worker.js` (or `.ts`) exists, `WorkboxWebpackPlugin.InjectManifest` processes it:

- Injects a precache manifest of all build assets
- The service worker controls caching strategy
- The default template from `cra-template` registers the service worker only in production

In development, `noopServiceWorkerMiddleware` serves a no-op service worker that clears any previously registered cache, preventing stale content.

---

## 5. Operations

### 5.1 The Four Commands

#### `react-scripts start` (scripts/start.js)

1. Sets `NODE_ENV=development`
2. Verifies required files exist
3. Detects available port (default 3000, auto-increments via `detect-port-alt`)
4. Creates webpack compiler with development config
5. Starts webpack-dev-server with HMR and error overlay
6. Opens browser (unless `BROWSER=none`)

Key dev server features:
- Hot Module Replacement via `webpackHotDevClient.js` (not webpack's default client)
- React Fast Refresh for state-preserving component updates (unless `FAST_REFRESH=false`)
- Error overlay (`react-error-overlay`) for runtime and compilation errors
- Proxy support (single-origin via `package.json` or multi-target via `src/setupProxy.js`)
- History API fallback for SPA routing
- Static file serving from `public/`

#### `react-scripts build` (scripts/build.js)

Described in Section 4.1 above. Exits with code 1 on failure (or when `CI=true` and warnings exist).

#### `react-scripts test` (scripts/test.js)

1. Sets `NODE_ENV=test`
2. Loads `.env` files (skips `.env.local`)
3. Configures Jest with `config/jest/` transforms
4. Runs in watch mode by default (unless `CI=true` or `--watchAll=false`)

See Section 8.4 for full testing details.

#### `react-scripts eject` (scripts/eject.js)

Eject is a one-way operation that copies all encapsulated configuration into the project:

1. Confirms via interactive prompt (unless `--force`)
2. Copies `config/` directory (webpack, Babel, Jest, env, paths, etc.)
3. Copies `scripts/` directory (start, build, test)
4. Updates `package.json`:
   - Moves all `react-scripts` dependencies to the project
   - Replaces script commands with direct `node scripts/*.js` calls
   - Removes `react-scripts` dependency
   - Adds `jest`, `babel`, and `eslintConfig` sections
5. Stages all changes in git (if repository detected)

> [!CAUTION]
> Ejecting is irreversible. Once ejected, the project assumes ownership of all configuration files. Future `react-scripts` updates (bug fixes, security patches, dependency upgrades) will not apply. Before ejecting, consider alternatives: `CRACO`, `react-app-rewired`, or `customize-cra` for non-destructive config overrides.

### 5.2 Preflight Checks

Before running any command, `react-scripts` performs a `verifyPackageTree()` check that detects mismatched versions of critical dependencies (Babel, webpack, Jest, ESLint). This catches scenarios where a parent project or global install provides a conflicting version.

Set `SKIP_PREFLIGHT_CHECK=true` to bypass this (not recommended for production).

### 5.3 Webpack Cache Management

CRA uses webpack 5's persistent filesystem cache stored in `node_modules/.cache/`:

```javascript
cache: {
  type: 'filesystem',
  version: environmentHash,  // Hash of NODE_ENV + all env vars
  cacheDirectory: paths.appWebpackCache,
  store: 'pack',
  buildDependencies: {
    defaultWebpack: ['webpack/lib/'],
    config: [__filename],
    tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f => fs.existsSync(f)),
  },
}
```

The cache is automatically invalidated when:
- Any environment variable changes (via `environmentHash`)
- webpack config file changes
- `tsconfig.json` or `jsconfig.json` changes

To manually clear the cache:

```bash
rm -rf node_modules/.cache
```

### 5.4 Error Handling

The error overlay (`react-error-overlay`) injects an iframe into the page to display:
- Compilation errors (webpack build failures)
- Runtime errors (uncaught exceptions, unhandled promise rejections)
- Source-mapped stack traces with click-to-open-in-editor

The overlay hooks into `window.onerror` and `window.onunhandledrejection`. In production builds, the overlay is not included.

> [!WARNING]
> The dev server's `DANGEROUSLY_DISABLE_HOST_CHECK` flag disables DNS rebinding protection. Only use this in trusted network environments. If you need to access the dev server from other devices, prefer `--host 0.0.0.0` with the default host check enabled.

---

## 6. Performance

### 6.1 Webpack Production Optimizations

| Optimization | Implementation | Impact |
|---|---|---|
| Code splitting | `splitChunks.chunks: 'all'` | Separates vendor code from application code |
| Tree shaking | `mode: 'production'` + `sideEffects` | Eliminates dead code exports |
| JS minification | TerserPlugin (parallel, ECMAScript 5 output) | 60-80% size reduction |
| CSS minification | CssMinimizerPlugin | Removes whitespace, deduplicates rules |
| Asset hashing | `[contenthash:8]` in filenames | Enables aggressive caching |
| Runtime inlining | InlineChunkHtmlPlugin | Saves one HTTP request for runtime chunk |
| Image inlining | url-loader with 10KB limit | Reduces HTTP requests for small images |
| Scope hoisting | `optimization.concatenateModules` | Reduces module wrapper overhead |
| Deterministic IDs | `optimization.moduleIds: 'deterministic'` | Stable chunk hashes across builds |

### 6.2 Development Performance

| Feature | Implementation | Impact |
|---|---|---|
| Fast Refresh | ReactRefreshWebpackPlugin | Sub-second updates, preserves state |
| Filesystem cache | webpack 5 persistent cache | Faster rebuilds after first compilation |
| `cheap-module-source-map` | devtool setting | Faster source maps (line-only) |
| Ignored node_modules | watchOptions.ignored (if configured) | Reduced filesystem watching overhead |
| Fork TS Checker | ForkTsCheckerWebpackPlugin | Type checking in separate process |

### 6.3 Build Size Analysis

CRA includes `FileSizeReporter` which reports gzipped sizes after each build:

```
File sizes after gzip:

  48.12 KB  build/static/js/main.a1b2c3d4.js
  1.42 KB   build/static/css/main.e5f6a7b8.css
```

For deeper analysis, the `asset-manifest.json` maps logical names to physical files with hashes, enabling automated size tracking.

### 6.4 CSS Performance

- **CSS Modules**: `.module.css` and `.module.scss` files get locally scoped class names via `css-loader` modules mode, using the ident pattern `[path][name]__[local]--[hash:base64:5]` (generated by `getCSSModuleLocalIdent`)
- **PostCSS Autoprefixer**: Automatically adds vendor prefixes based on browserslist
- **Tailwind CSS**: Auto-detected when `tailwind.config.js` exists in project root; PostCSS config includes tailwindcss plugin
- **MiniCssExtractPlugin**: Production CSS is extracted to separate files (development uses `style-loader` for HMR)

> [!NOTE]
> Sass support requires installing `sass` (Dart Sass). The webpack config conditionally enables `sass-loader` for `.scss` and `.sass` files, including CSS Module variants (`.module.scss`, `.module.sass`). No configuration is needed beyond the install.

---

## 7. Security

### 7.1 Environment Variable Isolation

Only variables prefixed with `REACT_APP_` are embedded in the client bundle. This is enforced in `config/env.js`:

```javascript
const REACT_APP = /^REACT_APP_/i;

function getClientEnvironment(publicUrl) {
  const raw = Object.keys(process.env)
    .filter(key => REACT_APP.test(key))
    .reduce((env, key) => {
      env[key] = process.env[key];
      return env;
    }, {
      NODE_ENV: process.env.NODE_ENV || 'development',
      PUBLIC_URL: publicUrl,
      WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
      WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
      WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
      FAST_REFRESH: process.env.FAST_REFRESH !== 'false',
    });
  // ...
}
```

> [!CAUTION]
> Any `REACT_APP_*` variable is embedded directly into the JavaScript bundle and visible to anyone who inspects the built files. Never store secrets, API keys with write access, database credentials, or other sensitive values in `REACT_APP_*` variables. These are for public configuration only (e.g., API base URLs, feature flags, analytics IDs).

### 7.2 Module Scope Enforcement

`ModuleScopePlugin` restricts imports to files within `src/` and `node_modules/`. This prevents:
- Accidentally importing build artifacts
- Importing files outside the source tree that webpack might not process correctly
- Breaking the build when files are in unexpected locations

Allowed exceptions: `package.json` (for reading `homepage`, `proxy`, etc.) and files in `node_modules/`.

### 7.3 Import Restriction — Confusing Browser Globals

`confusing-browser-globals` exports a list of 56 browser global variables (`event`, `name`, `status`, `length`, `origin`, `open`, `close`, etc.) that are restricted by the ESLint config. This prevents accidental use of global variables that shadow common local variable names:

```javascript
// ESLint error: Unexpected use of 'event'
function handleClick() {
  console.log(event); // Meant to use the parameter, accidentally got window.event
}
```

### 7.4 Host Check Protection

The webpack dev server validates the `Host` header to prevent DNS rebinding attacks. The `webpackDevServer.config.js` allows:
- `localhost` and loopback addresses
- The configured `HOST` environment variable
- Any host when `DANGEROUSLY_DISABLE_HOST_CHECK=true` (insecure)

### 7.5 HTTPS Configuration

For local HTTPS development:

```bash
HTTPS=true react-scripts start
```

For custom certificates (e.g., for testing with real domain names):

```bash
SSL_CRT_FILE=./cert.pem SSL_KEY_FILE=./key.pem HTTPS=true react-scripts start
```

The `getHttpsConfig.js` module reads and validates the certificate and key files, providing clear error messages if they are missing or unreadable.

### 7.6 Source Map Security

Production source maps are generated by default, exposing the original source code. For production deployments where source exposure is a concern:

```bash
GENERATE_SOURCEMAP=false react-scripts build
```

Alternatively, upload source maps to an error tracking service (Sentry, Bugsnag) and exclude `.map` files from the production server.

> [!IMPORTANT]
> The `asset-manifest.json` file lists all build outputs including source maps. If you serve this file publicly, automated tools can discover and download your source maps even if they are not linked in the JavaScript files.

---

## 8. Developer Internals

### 8.1 Webpack Configuration Deep Dive

`config/webpack.config.js` exports a function that takes `webpackEnv` (`'development'` or `'production'`) and returns the full webpack config. Key structural decisions:

#### Entry Points

```javascript
entry: [
  // Development: WebSocket client for HMR
  isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
  // Application entry
  paths.appIndexJs,
].filter(Boolean)
```

#### Output Configuration

```javascript
output: {
  path: paths.appBuild,
  pathinfo: isEnvDevelopment,        // Module path comments in dev
  filename: isEnvProduction
    ? 'static/js/[name].[contenthash:8].js'
    : 'static/js/bundle.js',
  chunkFilename: isEnvProduction
    ? 'static/js/[name].[contenthash:8].chunk.js'
    : 'static/js/[name].chunk.js',
  assetModuleFilename: 'static/media/[name].[hash][ext]',
  publicPath: paths.publicUrlOrPath,
}
```

#### Loader Pipeline (in order of rule matching)

| Rule | Test Pattern | Loader(s) | Notes |
|---|---|---|---|
| Source maps | `*.{js,mjs,jsx,ts,tsx,css}` | source-map-loader | Pre-loader; loads existing source maps from dependencies |
| Application JS | `*.{js,mjs,jsx,ts,tsx}` inside `appSrc` | babel-loader | With babel-preset-react-app; plugins include React Refresh (dev) |
| Dependency JS | `*.{js,mjs}` outside `appSrc` | babel-loader | Limited preset (no JSX, no TS); compiles modern JS in node_modules |
| CSS | `*.css` (not .module.css) | style-loader/MiniCssExtractPlugin, css-loader, postcss-loader | PostCSS with Autoprefixer (+ Tailwind if detected) |
| CSS Modules | `*.module.css` | Same as CSS + css-loader modules mode | Local scoped class names |
| Sass | `*.{scss,sass}` (not .module) | Same as CSS + resolve-url-loader + sass-loader | Requires `sass` package installed |
| Sass Modules | `*.module.{scss,sass}` | Same as Sass + css-loader modules mode | Local scoped class names |
| SVG (named import) | `*.svg` | @svgr/webpack + file-loader | Named imports get React components; default gets URL |
| Catch-all assets | Everything else | asset/resource | Emits file, returns URL |

#### Complete Plugin List

| Plugin | Environment | Purpose |
|---|---|---|
| HtmlWebpackPlugin | Both | Generates `index.html` with injected script/link tags |
| InlineChunkHtmlPlugin | Production | Inlines the runtime chunk script into HTML |
| InterpolateHtmlPlugin | Both | Replaces `%ENV_VARIABLE%` placeholders in `index.html` |
| ModuleNotFoundPlugin | Both | Friendly error messages for missing modules with install suggestions |
| DefinePlugin | Both | Injects `process.env.*` as compile-time constants |
| CaseSensitivePathsPlugin | Development | Catches case-sensitivity issues on case-insensitive filesystems |
| ReactRefreshWebpackPlugin | Development (FAST_REFRESH) | Enables React Fast Refresh HMR |
| MiniCssExtractPlugin | Production | Extracts CSS into separate files |
| WebpackManifestPlugin | Both | Generates `asset-manifest.json` |
| WorkboxWebpackPlugin.InjectManifest | Production (if SW exists) | Service worker precache manifest injection |
| ForkTsCheckerWebpackPlugin | Both (if TS) | TypeScript type checking in separate process |
| ESLintPlugin | Both (unless DISABLE_ESLINT_PLUGIN) | Runs ESLint during compilation |

### 8.2 Babel Configuration

`babel-preset-react-app` configures Babel with these presets and plugins:

#### Presets

| Preset | Config | Notes |
|---|---|---|
| `@babel/preset-env` | `useBuiltIns: 'entry'`, `corejs: 3` | Transpiles to target browsers |
| `@babel/preset-react` | `runtime: 'automatic'` (unless DISABLE_NEW_JSX_TRANSFORM) | JSX transformation |
| `@babel/preset-typescript` | (when `.tsx?` files) | TypeScript syntax stripping |
| `@babel/preset-flow` | (when flow detected) | Flow type stripping |

#### Plugins

| Plugin | Purpose |
|---|---|
| `@babel/plugin-transform-flow-strip-types` | Remove Flow annotations |
| `babel-plugin-named-asset-import` | Transform named SVG imports to @svgr paths |
| `@babel/plugin-proposal-decorators` | Stage 2 decorators (`legacy: false`) |
| `@babel/plugin-proposal-class-properties` | Class property syntax |
| `@babel/plugin-proposal-private-methods` | Private class methods |
| `@babel/plugin-proposal-private-property-in-object` | Private property `in` checks |
| `@babel/plugin-proposal-numeric-separator` | `1_000_000` syntax |
| `@babel/plugin-proposal-optional-chaining` | `?.` operator |
| `@babel/plugin-proposal-nullish-coalescing-operator` | `??` operator |
| `babel-plugin-macros` | Compile-time code generation (e.g., `preval`, `codegen`) |
| `react-refresh/babel` | React Fast Refresh (development only) |

### 8.3 ESLint Configuration

`eslint-config-react-app` extends/uses these plugins:

| Plugin/Config | Rules Category |
|---|---|
| `eslint-plugin-react` | React-specific rules (JSX, props, hooks usage) |
| `eslint-plugin-react-hooks` | `rules-of-hooks` (error), `exhaustive-deps` (warn) |
| `eslint-plugin-jsx-a11y` | Accessibility rules for JSX |
| `eslint-plugin-flowtype` | Flow type annotation rules |
| `eslint-plugin-import` | Import/export validation |
| `@typescript-eslint/eslint-plugin` | TypeScript-specific rules (when TS detected) |
| `confusing-browser-globals` | Restricted global variables |

ESLint runs as a webpack plugin (`ESLintPlugin`) during compilation, reporting errors in the terminal and error overlay. The `eslintFormatter.js` utility formats output with file paths and line numbers.

### 8.4 Testing Infrastructure

#### Jest Configuration

CRA configures Jest 27 with the following from `scripts/test.js` and the `createJestConfig` function:

```javascript
{
  roots: ['<rootDir>/src'],
  collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
  setupFiles: ['react-app-polyfill/jsdom'],
  setupFilesAfterFramework: [paths.testsSetup],  // src/setupTests.{js,ts}
  testMatch: [
    '<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
    '<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}',
  ],
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': 'config/jest/babelTransform.js',
    '^.+\\.css$': 'config/jest/cssTransform.js',
    '^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'config/jest/fileTransform.js',
  },
  moduleNameMapper: { '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy' },
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
}
```

#### Custom Transforms

| Transform | File | Purpose |
|---|---|---|
| `babelTransform.js` | `*.{js,jsx,ts,tsx,mjs,cjs}` | Runs Babel with `babel-preset-react-app` in test mode |
| `cssTransform.js` | `*.css` | Returns empty module (CSS is irrelevant in tests) |
| `fileTransform.js` | All other files | Returns the filename as the module's default export |

#### Watch Mode

In non-CI environments, Jest runs in `--watch` mode by default (if git/hg is detected) or `--watchAll` otherwise. The `jest-watch-typeahead` plugins add interactive filtering by filename and test name.

> [!TIP]
> The `src/setupTests.js` (or `.ts`) file runs before every test file. Use it to configure testing-library matchers, mock global APIs, or set up test fixtures. The default template includes `@testing-library/jest-dom` for DOM assertion matchers like `toBeInTheDocument()` and `toHaveTextContent()`.

### 8.5 react-dev-utils Module Reference

All 33 utility modules in `packages/react-dev-utils/` (91 KB total):

| Module | Exports | Purpose |
|---|---|---|
| `browsersHelper.js` | `checkBrowsers()`, `defaultBrowsers` | Ensure browserslist is configured; prompts to add defaults |
| `chalk.js` | Re-export of `chalk` | Centralized chalk dependency |
| `checkRequiredFiles.js` | `checkRequiredFiles(files[])` | Verifies specified files exist; logs missing files |
| `clearConsole.js` | `clearConsole()` | Clears terminal output (respects `process.stdout.isTTY`) |
| `crossSpawn.js` | Re-export of `cross-spawn` | Cross-platform child process spawning |
| `errorOverlayMiddleware.js` | Express middleware | Dev server endpoint for launching editor from error overlay |
| `eslintFormatter.js` | `formatter(results)` | Formats ESLint results for terminal; respects `ESLINT_NO_DEV_ERRORS` |
| `evalSourceMapMiddleware.js` | Express middleware | Serves source maps for eval'd code in development |
| `FileSizeReporter.js` | `measureFileSizesBeforeBuild()`, `printFileSizesAfterBuild()` | Reports gzipped file sizes with before/after diff |
| `formatWebpackMessages.js` | `formatWebpackMessages({errors, warnings})` | Transforms webpack stats into human-readable messages |
| `getCSSModuleLocalIdent.js` | `getCSSModuleLocalIdent(context, ident, name)` | Generates CSS Module class names: `[path][name]__[local]--[hash:base64:5]` |
| `getProcessForPort.js` | `getProcessForPort(port)` | Identifies which process occupies a given port |
| `getPublicUrlOrPath.js` | `getPublicUrlOrPath(isDev, homepage, envPublicUrl)` | Resolves PUBLIC_URL from environment or package.json homepage |
| `globby.js` | Re-export of `globby` | Centralized globby dependency |
| `ignoredFiles.js` | `ignoredFiles(appSrc)` | Returns regex for webpack watchOptions to ignore `node_modules` |
| `immer.js` | Re-export of `immer` | Centralized immer dependency |
| `InlineChunkHtmlPlugin.js` | webpack plugin class | Inlines specified chunks as `<script>` tags in HTML |
| `InterpolateHtmlPlugin.js` | webpack plugin class | Replaces `%VARIABLE%` placeholders in `HtmlWebpackPlugin` output |
| `launchEditor.js` | `launchEditor(file, line, column)` | Opens file in editor; reads `REACT_EDITOR`, `VISUAL`, `EDITOR` |
| `ModuleNotFoundPlugin.js` | webpack plugin class | Enhances "module not found" errors with install suggestions |
| `ModuleScopePlugin.js` | webpack resolver plugin class | Restricts imports to `src/` and `node_modules/` |
| `noopServiceWorkerMiddleware.js` | Express middleware | Serves a no-op service worker in development |
| `openBrowser.js` | `openBrowser(url)` | Opens URL in browser; reads `BROWSER` and `BROWSER_ARGS` env vars |
| `openChrome.applescript` | AppleScript | macOS-specific: opens/reuses Chrome tab |
| `printBuildError.js` | `printBuildError(error)` | Formats and prints webpack build errors |
| `printHostingInstructions.js` | `printHostingInstructions(appPackage, publicUrl, publicPath, buildFolder, useYarn)` | Post-build deployment instructions |
| `redirectServedPathMiddleware.js` | Express middleware | Redirects `/` to `PUBLIC_URL` path in dev server |
| `typescriptFormatter.js` | `formatter(issue, useColors)` | Formats TypeScript diagnostic messages |
| `WebpackDevServerUtils.js` | `choosePort()`, `createCompiler()`, `prepareProxy()`, `prepareUrls()` | Dev server utilities: port detection, compiler setup, proxy config, URL resolution |
| `webpackHotDevClient.js` | webpack entry | Custom HMR client with error overlay integration; reads `WDS_SOCKET_*` |
| `getCacheIdentifier.js` | `getCacheIdentifier(environment, packages[])` | Generates cache key from environment and package versions |
| `ForkTsCheckerWarningWebpackPlugin.js` | webpack plugin class | Converts TypeScript errors to warnings (when `TSC_COMPILE_ON_ERROR=true`) |
| `getHttpsConfig.js` | `getHttpsConfig()` | Reads SSL_CRT_FILE/SSL_KEY_FILE, validates, returns HTTPS config object |

### 8.6 react-error-overlay Internals

The error overlay is a standalone package that renders compilation and runtime errors in an iframe injected into the page:

- **iframe isolation** — Styles and scripts do not conflict with the application
- **Source mapping** — Uses `source-map` library to map transpiled stack traces back to original source
- **Click-to-source** — Clicking a stack frame calls the dev server's launch-editor endpoint
- **Runtime hooks** — Listens to `window.onerror` and `window.onunhandledrejection`
- **API** — `startReportingRuntimeErrors({onError, filename})`, `stopReportingRuntimeErrors()`, `setEditorHandler(handler)`, `dismissBuildError()`, `reportBuildError(error)`

The overlay is included only in development builds. It is imported by `webpackHotDevClient.js`.

### 8.7 create-react-app CLI Internals

The CLI package (`packages/create-react-app/`) handles project scaffolding:

#### CLI Arguments

| Argument | Description |
|---|---|
| `<project-directory>` | Required. Name of the directory to create |
| `--verbose` | Print additional logs during installation |
| `--info` | Print environment diagnostic information (via `envinfo`) |
| `--scripts-version <version>` | Use a specific version of react-scripts (or a custom fork) |
| `--template <template>` | Use a specific template (default: `cra-template`) |
| `--use-pnp` | Enable Yarn Plug'n'Play |

#### Scaffolding Process

1. Validates project name (`validate-npm-package-name`)
2. Creates project directory
3. Writes initial `package.json`
4. Detects package manager (npm, yarn, or pnpm)
5. Installs `react`, `react-dom`, and `react-scripts` (or specified `--scripts-version`)
6. Downloads and extracts template package
7. Runs `react-scripts init` which:
   - Copies template files into the project
   - Sets up `package.json` scripts (`start`, `build`, `test`, `eject`)
   - Initializes git repository
   - Displays success message with next steps

### 8.8 Package Manager Detection

The CLI and react-scripts detect the active package manager through multiple signals:

| Signal | Detected Manager |
|---|---|
| `yarn.lock` exists | Yarn |
| `pnpm-lock.yaml` exists | pnpm |
| `npm_config_user_agent` contains `yarn` | Yarn |
| `npm_config_user_agent` contains `pnpm` | pnpm |
| Default | npm |

This affects install commands, lockfile handling, and post-build instructions.

---

## 9. Integration Points

### 9.1 Customization Without Ejecting

Several community tools allow overriding CRA's webpack config without ejecting:

| Tool | Approach |
|---|---|
| `craco` (Create React App Configuration Override) | `craco.config.js` with webpack/babel/eslint/jest overrides |
| `react-app-rewired` | `config-overrides.js` with webpack-merge-style patching |
| `customize-cra` | Composable override functions for use with react-app-rewired |
| `rescripts` | Multi-file override system |

These tools work by intercepting the config before it reaches webpack and applying user-defined modifications.

### 9.2 Template System

Custom templates are npm packages named `cra-template-*`. Template structure:

```
cra-template-{name}/
├── template/           # Files copied into the new project
│   ├── public/
│   ├── src/
│   └── gitignore       # Renamed to .gitignore
├── template.json       # Additional dependencies and scripts
└── package.json        # Template package metadata
```

`template.json` supports:

```json
{
  "dependencies": {
    "additional-package": "^1.0.0"
  },
  "scripts": {
    "custom-script": "echo hello"
  }
}
```

### 9.3 Monorepo Compatibility

CRA projects can live inside monorepos with caveats:

- `ModuleScopePlugin` restricts imports to `src/` — shared packages must be in `node_modules` (hoisted) or the plugin must be disabled (via eject or CRACO)
- `babel-loader` only processes files inside `appSrc` — shared source outside `src/` will not be transpiled
- Webpack's `resolve.modules` includes only the project's `node_modules`, not parent directories (hoisting handles this for most package managers)

### 9.4 CI/CD Integration

| CI Platform | Configuration Notes |
|---|---|
| GitHub Actions | Set `CI: true` in env; caching `node_modules` and `~/.npm` speeds builds |
| GitLab CI | Set `CI=true`; use `npm ci` for deterministic installs |
| Travis CI | `CI` is set automatically; `cache: npm` recommended |
| Jenkins | Set `CI=true` explicitly; allocate sufficient memory for webpack |
| Netlify | `CI` is set automatically; build command is `npm run build` |
| Vercel | Detects CRA automatically; zero-config deployment |

For memory-constrained CI environments:

```bash
NODE_OPTIONS=--max-old-space-size=4096 react-scripts build
```

> [!NOTE]
> When `CI=true`, the build process treats all ESLint warnings as errors and fails the build. The test runner also runs all tests once and exits (no watch mode). This is the recommended configuration for all CI pipelines.

### 9.5 Known Issues and Workarounds

| Issue | Symptoms | Workaround |
|---|---|---|
| Node 17+ OpenSSL (#17216) | `ERR_OSSL_EVP_UNSUPPORTED` | `NODE_OPTIONS=--openssl-legacy-provider` |
| `.env` not loading (#11951, #11954) | Environment variables undefined at runtime | Ensure `REACT_APP_` prefix; restart dev server after changes |
| `.env` changes on restart (#13416) | Changed variables not picked up | Clear webpack cache: `rm -rf node_modules/.cache` |
| `react-scripts` not found (#17117) | Command not recognized | Reinstall: `rm -rf node_modules && npm install` |
| `interopRequireDefault` (#6398) | Cannot find module error | Version mismatch; align `react-scripts` with project dependencies |
| `.eslintcache` generation (#10161) | File appears in project root | Add `.eslintcache` to `.gitignore` |
| Nullish assignment (#9908) | Syntax error on `??=` | Requires react-scripts 5.x or newer Babel config |
| Netlify build failures (#17208) | Build fails on Netlify | Ensure `CI=true` is set; check Node version compatibility |

### 9.6 Dependency Version Matrix

Core dependency versions locked by react-scripts 5.1.0:

| Dependency | Version | Purpose |
|---|---|---|
| webpack | 5 | Module bundler |
| Babel | 7 | JavaScript/TypeScript transpiler |
| ESLint | 8 | Code linting |
| Jest | 27 | Test runner |
| PostCSS | 8 | CSS processing |
| Terser | (webpack 5 built-in) | JS minification |
| css-minimizer-webpack-plugin | (latest compatible) | CSS minification |
| html-webpack-plugin | (latest compatible) | HTML generation |
| workbox-webpack-plugin | (latest compatible) | Service worker generation |
| @svgr/webpack | (latest compatible) | SVG-to-React-component |
| dotenv | (latest compatible) | .env file loading |
| dotenv-expand | (latest compatible) | Variable expansion in .env |

> [!WARNING]
> Installing different versions of these dependencies alongside `react-scripts` triggers the preflight version check and may cause unpredictable behavior. If the preflight check blocks startup, investigate the version conflict rather than setting `SKIP_PREFLIGHT_CHECK=true`.

### 9.7 Migration Paths

Since CRA is deprecated, the recommended migration targets are:

| Target | Approach | Effort |
|---|---|---|
| Vite | Replace react-scripts with `@vitejs/plugin-react`; migrate config | Medium |
| Next.js | Restructure to pages/app router; significant architecture change | High |
| Remix | Restructure to loaders/actions pattern | High |
| Manual webpack | Eject first, then modernize the ejected config | Medium |
| CRACO/react-app-rewired | Stay on CRA with custom overrides (short-term only) | Low |

For Vite migration, the key changes are:
- Replace `react-scripts` scripts with `vite` / `vite build` / `vitest`
- Convert `REACT_APP_*` env vars to `VITE_*`
- Move `public/index.html` to project root and add `<script type="module" src="/src/index.jsx">` tag
- Replace `%PUBLIC_URL%` with Vite's asset handling
- Update `jest.config` to `vitest.config` if using Vitest

---

_Generated May 2026 from facebook/create-react-app at 6254386. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
