# How the Webpack Configuration Works in Create React App: A Complete Guide to react-scripts

> Learn how Create React App's react-scripts package manages a hidden Webpack configuration for seamless TypeScript compilation and asset optimization without manual setup.

- Repository: [Meta/create-react-app](https://github.com/facebook/create-react-app)
- Tags: deep-dive
- Published: 2026-02-26

---

**Create React App uses a sophisticated, environment-aware Webpack configuration hidden inside the `react-scripts` package that handles everything from TypeScript compilation to asset optimization without requiring manual setup.**

The webpack configuration in Create React App (CRA) is one of the most influential build setups in the React ecosystem. According to the facebook/create-react-app source code, the configuration lives in `packages/react-scripts/config/` and provides a zero-config experience while remaining extensible through environment variables and third-party tools.

## Core Webpack Configuration Files in react-scripts

CRA splits its webpack logic across multiple specialized files to handle different environments and concerns.

### webpack.config.js

The primary configuration file located at [`packages/react-scripts/config/webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js) exports a function that generates a complete webpack configuration object based on the current environment. This single file handles both development and production builds, switching settings dynamically based on the `webpackEnv` parameter (lines 103-104).

### webpackDevServer.config.js

Development server settings are isolated in [`packages/react-scripts/config/webpackDevServer.config.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpackDevServer.config.js). This configuration powers the `npm start` command and handles hot reloading, proxy settings, and the error overlay (lines 89-92).

### Supporting Configuration Modules

Several utility modules feed into the main webpack config:

- **[`paths.js`](https://github.com/facebook/create-react-app/blob/main/paths.js)** – Resolves project paths like `appSrc`, `appPublic`, and `appIndexJs`
- **[`env.js`](https://github.com/facebook/create-react-app/blob/main/env.js)** – Loads environment variables and prepares the `process.env` object for `DefinePlugin`
- **[`modules.js`](https://github.com/facebook/create-react-app/blob/main/modules.js)** – Handles additional module lookup paths and webpack aliases via [`jsconfig.json`](https://github.com/facebook/create-react-app/blob/main/jsconfig.json) or [`tsconfig.json`](https://github.com/facebook/create-react-app/blob/main/tsconfig.json)
- **[`createEnvironmentHash.js`](https://github.com/facebook/create-react-app/blob/main/createEnvironmentHash.js)** – Generates cache-busting hashes based on environment variables

## Entry Points and Output Configuration

CRA follows conventional webpack patterns for entry and output but adds specific optimizations for React applications.

### Application Entry Point

The webpack `entry` property points to your project's [`src/index.js`](https://github.com/facebook/create-react-app/blob/main/src/index.js) (or `.tsx`) file, resolved through `paths.appIndexJs` (lines 101-114). In development, CRA injects additional entry points for the webpack dev client and react-refresh runtime.

### Build Output

Production builds output to the `build/` directory with a specific static asset structure:

```javascript
// Output configuration (lines 221-227)
output: {
  path: paths.appBuild,
  pathinfo: isEnvDevelopment,
  filename: 'static/js/[name].[contenthash:8].js',
  chunkFilename: 'static/js/[name].[contenthash:8].chunk.js',
  assetModuleFilename: 'static/media/[name].[hash][ext]',
  publicPath: paths.publicUrlOrPath,
}

```

The `contenthash` in filenames enables aggressive caching strategies, while `assetModuleFilename` handles images and fonts.

## Build Mode, Source Maps, and Persistent Caching

CRA's webpack configuration adapts significantly based on whether you're running in development or production mode.

### Environment Mode Switching

The configuration function accepts a `webpackEnv` parameter that sets `mode` to either `'development'` or `'production'` (lines 103-104). This single variable cascades through the entire configuration, affecting optimization settings, plugin selection, and loader behavior.

### Source Map Configuration

Source map generation varies by environment:

- **Development**: Uses `cheap-module-source-map` for fast rebuilds with original line numbers (line 106)
- **Production**: Uses `source-map` for full fidelity debugging unless `GENERATE_SOURCEMAP=false` is set (lines 108-110)

### Filesystem Caching

CRA implements webpack 5's persistent filesystem caching to speed up subsequent builds:

```javascript
// Cache configuration (lines 42-48)
cache: {
  type: 'filesystem',
  version: createEnvironmentHash(env.raw),
  cacheDirectory: paths.appWebpackCache,
  store: 'pack',
  buildDependencies: {
    defaultWebpack: ['webpack/lib/'],
    config: [__filename],
    tsconfig: [paths.appTsConfig, paths.appJsConfig].filter(f => fs.existsSync(f)),
  },
},

```

The `createEnvironmentHash` function generates a unique version string based on environment variables, ensuring the cache invalidates when relevant configuration changes.

## Module Resolution and Aliases

CRA configures webpack's resolution rules to support modern JavaScript ecosystems while maintaining compatibility.

### Module Lookup Paths

The `resolve.modules` configuration prioritizes the project's `node_modules` directory, then checks any additional paths defined in `modules.additionalModulePaths` (lines 10-13). This ensures local dependencies take precedence over global installations.

### File Extensions

Supported extensions are dynamically generated based on whether TypeScript is detected in the project:

```javascript
// Extension resolution (lines 19-22)
extensions: paths.moduleFileExtensions
  .map(ext => `.${ext}`)
  .filter(ext => useTypeScript || !ext.includes('ts')),

```

This filters out TypeScript extensions if no [`tsconfig.json`](https://github.com/facebook/create-react-app/blob/main/tsconfig.json) is present.

### Alias Configuration

CRA sets up specific aliases for compatibility:

- **`react-native` → `react-native-web`**: Allows code sharing between React Native and web projects (lines 23-27)
- **Profiling aliases**: When `--profile` flag is used, swaps React builds for profiling versions (lines 28-31)

## Webpack Loaders in Create React App

The `module.rules` array in CRA's webpack configuration uses a `oneOf` structure, meaning the first matching loader wins. This section breaks down how different file types are processed.

### JavaScript and TypeScript Processing

All JavaScript and TypeScript files inside `src/` pass through `babel-loader` with the `babel-preset-react-app` preset (lines 16-20). This handles:

- JSX transformation
- TypeScript compilation (if applicable)
- Modern JavaScript syntax (ES6+) transpilation
- Polyfill injection based on target browsers

```javascript
// Example: Babel loader configuration for JS/TS
{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  include: paths.appSrc,
  loader: require.resolve('babel-loader'),
  options: {
    customize: require.resolve('babel-preset-react-app/webpack-overrides'),
    presets: [require.resolve('babel-preset-react-app')],
    // ... additional options
  },
}

```

### Stylesheets: CSS, CSS Modules, and SASS

CRA handles styling through a sophisticated loader chain that differs between development and production.

**Standard CSS** (lines 18-27):
- Development: `style-loader` injects styles into the DOM
- Production: `MiniCssExtractPlugin.loader` extracts CSS to separate files
- Both: `css-loader` resolves imports and `postcss-loader` processes PostCSS plugins (including autoprefixer)

**CSS Modules** (lines 33-43):
Files matching `*.module.css` use the same loader chain but with `modules: { mode: 'local' }` enabled, scoping class names locally by default.

**SASS/SCSS** (lines 45-62):
Adds `sass-loader` to the chain for `.scss` and `.sass` files, with identical CSS Modules support for `*.module.scss` files.

### Static Assets: Images, SVGs, and Fonts

CRA uses webpack 5's Asset Modules for handling static files with intelligent optimization strategies.

**Images** (`bmp`, `gif`, `jpg`, `png`):
Uses `asset` type with inline threshold. Files ≤ 10,000 bytes (configurable via `IMAGE_INLINE_SIZE_LIMIT`) become data URLs; larger files emit to `static/media/` (lines 80-86).

**SVGs**:
Special handling via `@svgr/webpack` (lines 90-104). SVGs import as React components by default, with `file-loader` fallback for URLs.

**Fallback Assets**:
Any unmatched files (fonts, videos, etc.) use `asset/resource` (lines 96-99). The "file" loader is deliberately last; new loaders must be inserted before it (lines 100-102).

## Essential Webpack Plugins in Create React App

CRA's webpack configuration employs numerous plugins to handle everything from HTML generation to service worker creation.

**HtmlWebpackPlugin** (lines 6-13):
Injects generated JS/CSS bundles into [`public/index.html`](https://github.com/facebook/create-react-app/blob/main/public/index.html) and minifies the HTML in production.

**InlineChunkHtmlPlugin** (lines 33-38):
Inlines the small runtime chunk directly into HTML when `INLINE_RUNTIME_CHUNK` environment variable is true, reducing HTTP requests.

**DefinePlugin** (lines 49-53):
Injects `process.env.*` variables parsed by [`env.js`](https://github.com/facebook/create-react-app/blob/main/env.js), making environment variables available at build time.

**MiniCssExtractPlugin** (lines 65-71):
Extracts CSS into separate files in production builds rather than injecting into the DOM.

**WebpackManifestPlugin** (lines 72-90):
Generates [`asset-manifest.json`](https://github.com/facebook/create-react-app/blob/main/asset-manifest.json) mapping original file names to hashed output names, essential for server-side rendering.

**WorkboxWebpackPlugin** (lines 106-117):
Generates a service worker when [`src/service-worker.js`](https://github.com/facebook/create-react-app/blob/main/src/service-worker.js) exists, enabling offline capabilities.

**ForkTsCheckerWebpackPlugin** (lines 118-146):
Runs TypeScript type checking in a separate process to avoid blocking the main compilation thread (only active when [`tsconfig.json`](https://github.com/facebook/create-react-app/blob/main/tsconfig.json) exists).

**ESLintPlugin** (lines 149-159):
Lints source files during the build process, with optional failure on errors in production.

**ReactRefreshWebpackPlugin** (lines 54-58):
Enables Fast Refresh (hot reloading) for React components in development mode.

**CaseSensitivePathsPlugin** (lines 34-36):
Prevents build failures on case-insensitive file systems by enforcing case sensitivity.

**IgnorePlugin** (lines 95-99):
Excludes Moment.js locales from the bundle unless explicitly imported, reducing bundle size.

## Development Server Configuration

The [`webpackDevServer.config.js`](https://github.com/facebook/create-react-app/blob/main/webpackDevServer.config.js) file configures the development environment that powers `npm start`, extending the base webpack configuration with development-specific features.

**Allowed Hosts** (lines 24-27):
Disables host checks when no proxy is configured, otherwise respects the `HOST` environment variable and `allowedHost` settings to prevent DNS rebinding attacks.

**Static File Serving** (lines 68-71):
Serves only the `public` folder, never the entire project directory, preventing accidental exposure of source files.

**Error Overlay** (lines 89-92):
Displays a full-screen error overlay for compilation errors while suppressing warnings, ensuring developers immediately see breaking issues.

**Custom Middleware Stack** (lines 13-27):
- `evalSourceMapMiddleware`: Enables the error overlay to fetch original source maps
- `redirectServedPath`: Rewrites unknown URLs to [`index.html`](https://github.com/facebook/create-react-app/blob/main/index.html) for single-page application routing
- `noopServiceWorkerMiddleware`: Removes any service workers registered from previous production builds to prevent caching issues during development

## Extending the Webpack Configuration Without Ejecting

While CRA hides the webpack configuration to provide a zero-config experience, you can customize it without ejecting using community tools that intercept the config object before it reaches webpack.

### Using CRACO

CRACO (Create React App Configuration Override) allows you to modify the webpack configuration programmatically:

```javascript
// craco.config.js (project root)
module.exports = {
  webpack: {
    configure: (webpackConfig) => {
      // Example: add a custom plugin to Babel
      const babelLoader = webpackConfig.module.rules.find(
        r => r.oneOf && r.oneOf.some(l => l.loader && l.loader.includes('babel-loader'))
      );
      if (babelLoader) {
        const babelRule = babelLoader.oneOf.find(l => l.loader && l.loader.includes('babel-loader'));
        babelRule.options.plugins = [
          ...(babelRule.options.plugins || []), 
          'babel-plugin-styled-components'
        ];
      }
      return webpackConfig;
    },
  },
};

```

This approach works because CRA's webpack config is exported as a plain JavaScript object, allowing the `configure` function to receive and modify that object before it is passed to webpack.

### Using react-app-rewired

react-app-rewired provides a simpler functional approach to config modification:

```javascript
// config-overrides.js
module.exports = function override(config) {
  // Add a loader for Markdown files
  config.module.rules.push({
    test: /\.md$/,
    use: 'raw-loader',
  });
  return config;
};

```

When running `npm start` or `npm run build` with `react-app-rewired`, the additional rule is inserted **before** the final fallback asset loader, respecting CRA's architectural rule that new loaders must precede the file loader (lines 100-102 of webpack.config.js).

## Summary

- **Create React App** encapsulates its webpack configuration in [`packages/react-scripts/config/webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js) and [`webpackDevServer.config.js`](https://github.com/facebook/create-react-app/blob/main/webpackDevServer.config.js), providing a zero-config experience for React development.
- The **entry point** defaults to [`src/index.js`](https://github.com/facebook/create-react-app/blob/main/src/index.js) with output directed to `build/static/js` using content hashing for cache busting.
- **Filesystem caching** uses `createEnvironmentHash` to persist build data between sessions, significantly speeding up subsequent builds.
- The **loader chain** processes JavaScript via `babel-loader`, styles through `css-loader`/`postcss-loader` (with `MiniCssExtractPlugin` in production), and assets using webpack 5's Asset Modules.
- **Key plugins** include `HtmlWebpackPlugin` for HTML generation, `DefinePlugin` for environment variables, `ForkTsCheckerWebpackPlugin` for TypeScript checking, and `ReactRefreshWebpackPlugin` for hot reloading.
- You can **extend the configuration** without ejecting using tools like **CRACO** or **react-app-rewired** to modify the config object before it reaches webpack.

## Frequently Asked Questions

### Where is the webpack config located in Create React App?

The webpack configuration is hidden inside the `react-scripts` package at [`node_modules/react-scripts/config/webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/node_modules/react-scripts/config/webpack.config.js). The main file is [`packages/react-scripts/config/webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js) in the source repository, which exports a function that generates configuration based on the current environment (development or production).

### How do I modify the webpack configuration without ejecting?

You can use community tools like **CRACO** (Create React App Configuration Override) or **react-app-rewired** to intercept and modify the webpack config object before it is passed to the compiler. These tools allow you to add loaders, plugins, or aliases while maintaining the ability to update `react-scripts` without ejecting.

### What webpack loaders does CRA use for TypeScript?

CRA processes TypeScript files using `babel-loader` with `babel-preset-react-app` rather than `ts-loader`. This approach transpiles TypeScript during the main compilation while `ForkTsCheckerWebpackPlugin` runs type checking in a separate process to avoid blocking the build. The configuration handles `.ts`, `.tsx`, `.js`, and `.jsx` extensions found in `paths.moduleFileExtensions`.

### How does Create React App handle environment variables in webpack?

CRA uses webpack's `DefinePlugin` to inject environment variables at build time. The [`env.js`](https://github.com/facebook/create-react-app/blob/main/env.js) module scans for variables prefixed with `REACT_APP_` and creates a stringified object that `DefinePlugin` embeds into the bundle. This makes `process.env.REACT_APP_VARIABLE_NAME` available in your application code, with values determined when webpack runs rather than at runtime in the browser.