# What Is ForkTsCheckerWebpackPlugin and How It Works in Create React App

> Learn how ForkTsCheckerWebpackPlugin enhances Create React App by running TypeScript type-checking in a separate process for faster builds and accurate error reporting.

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

---

**ForkTsCheckerWebpackPlugin is a Webpack plugin that runs TypeScript type-checking in a separate worker process to prevent blocking the main compilation thread, enabling fast incremental builds in Create React App (CRA) while maintaining accurate error reporting.**

Create React App leverages `ForkTsCheckerWebpackPlugin` to provide non-blocking TypeScript type-checking during development. By delegating type validation to a forked process, CRA ensures that Webpack's dev server remains responsive while still surfacing type errors to developers. This integration is handled through a thin wrapper in `react-dev-utils` and configured conditionally within CRA's Webpack setup.

## How ForkTsCheckerWebpackPlugin Functions in CRA

### Architecture and Process Isolation

The plugin operates by spawning a dedicated worker process that runs the TypeScript compiler independently from Webpack's main thread. This architecture prevents type-checking from stalling the incremental build process, allowing developers to see updated bundles in the browser while type validation continues in the background.

### The react-dev-utils Wrapper

Rather than importing the plugin directly, CRA uses a thin re-export layer located at [`packages/react-dev-utils/ForkTsCheckerWebpackPlugin.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/ForkTsCheckerWebpackPlugin.js). This wrapper simply requires the upstream `fork-ts-checker-webpack-plugin` package and exports it unchanged:

```javascript
// packages/react-dev-utils/ForkTsCheckerWebpackPlugin.js
var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = ForkTsCheckerWebpackPlugin;

```

This abstraction allows CRA to pin specific versions in [`react-dev-utils/package.json`](https://github.com/facebook/create-react-app/blob/main/react-dev-utils/package.json) while providing a stable import interface for the main Webpack configuration.

## Integration in Webpack Configuration

CRA conditionally instantiates `ForkTsCheckerWebpackPlugin` within [`packages/react-scripts/config/webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack.config.js) based on two criteria: the project must contain a [`tsconfig.json`](https://github.com/facebook/create-react-app/blob/main/tsconfig.json) (indicating TypeScript usage), and the build must be in development mode.

The plugin configuration includes several critical parameters:

```javascript
// packages/react-scripts/config/webpack.config.js
const ForkTsCheckerWebpackPlugin = isEnvDevelopment
  ? require('react-dev-utils/ForkTsCheckerWebpackPlugin')
  : null;

// Within the plugins array:
...(isEnvDevelopment && paths.isTsProject
  ? [
      new ForkTsCheckerWebpackPlugin({
        async: true,
        typescript: {
          diagnosticOptions: {
            semantic: true,
            syntactic: true,
          },
        },
        eslint: {
          files: paths.appSrc,
        },
      }),
    ]
  : []),

```

Key configuration options include:

- **`async: true`** – Enables non-blocking execution, allowing Webpack to proceed with compilation while type-checking runs.
- **`typescript.diagnosticOptions`** – Enables both semantic and syntactic error checking.
- **`eslint`** – When ESLint is enabled in a TypeScript project, the plugin lints source files within the same worker process.

## Error Handling and Developer Experience

Errors generated by `ForkTsCheckerWebpackPlugin` are processed through CRA's `formatWebpackMessages` utility located in [`packages/react-dev-utils/formatWebpackMessages.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/formatWebpackMessages.js). This transforms raw TypeScript diagnostic output into readable terminal messages.

The plugin's asynchronous nature means:

- **Fast refresh** remains unblocked during type-checking.
- **Type errors appear after** the initial successful compilation.
- **Browser overlay** displays errors if they prevent successful execution.

When running `npm start` in a TypeScript CRA project, developers see output like:

```bash
Compiled successfully!

./src/App.tsx
  TS2322: Type 'string' is not assignable to type 'number'.

```

This indicates the bundle compiled (enabling fast iteration) but type issues require attention.

## Summary

- **ForkTsCheckerWebpackPlugin** runs TypeScript type-checking in a separate worker process to prevent blocking Webpack's main thread.
- CRA implements the plugin through a **thin wrapper** in `react-dev-utils` that re-exports the official package.
- The plugin is **conditionally enabled** only in development mode for TypeScript projects (`isEnvDevelopment && paths.isTsProject`).
- Configuration emphasizes **asynchronous execution** (`async: true`) and comprehensive diagnostic checking.
- Errors are formatted through CRA's utility system and displayed in the terminal and browser overlay without stopping the dev server.

## Frequently Asked Questions

### Why does Create React App use ForkTsCheckerWebpackPlugin instead of ts-loader?

CRA uses `ForkTsCheckerWebpackPlugin` alongside `babel-loader` rather than `ts-loader` to separate transpilation from type-checking. Babel handles fast JavaScript/TypeScript transformation during the Webpack build, while the plugin performs type-checking asynchronously in a background process. This architecture provides faster incremental builds during development while maintaining strict type safety.

### Does ForkTsCheckerWebpackPlugin run during production builds in CRA?

No, the plugin is explicitly disabled in production builds. In [`webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/webpack.config.js), the conditional check `isEnvDevelopment && paths.isTsProject` ensures the plugin only instantiates during development. Production builds rely on the TypeScript compiler (`tsc`) or build-time checks rather than the Webpack plugin to ensure type safety before deployment.

### How does CRA handle errors from ForkTsCheckerWebpackPlugin?

CRA processes plugin errors through the `formatWebpackMessages` utility in [`packages/react-dev-utils/formatWebpackMessages.js`](https://github.com/facebook/create-react-app/blob/main/packages/react-dev-utils/formatWebpackMessages.js). This transforms TypeScript diagnostic output into human-readable terminal messages. During development, type errors appear after the initial successful compilation and display in both the terminal and the browser error overlay, but they do not stop the hot-reloading dev server.

### Can I customize ForkTsCheckerWebpackPlugin options in CRA without ejecting?

Without ejecting, you cannot directly modify the plugin configuration in [`webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/webpack.config.js). However, you can influence behavior through [`tsconfig.json`](https://github.com/facebook/create-react-app/blob/main/tsconfig.json) settings (which the plugin respects) and ESLint configuration files. For advanced customization of plugin options like memory limits or specific diagnostic overrides, you would need to use tools like `react-app-rewired` or eject from CRA to modify [`webpack.config.js`](https://github.com/facebook/create-react-app/blob/main/webpack.config.js) directly.