Skip to main content
The Next.js Compiler is written in Rust using SWC. It replaces Babel for transforming individual files and Terser for minifying output bundles. Compilation with the SWC compiler is 17x faster than Babel and has been enabled by default since Next.js 12.

Why SWC

Next.js uses SWC for several reasons:
  • Performance — ~3x faster Fast Refresh and ~5x faster production builds compared to Babel.
  • Extensibility — SWC can be used as a crate inside Next.js without forking the library.
  • WebAssembly support — Rust’s WASM target means Next.js can compile on any platform, including environments where native binaries are unavailable.
  • Ecosystem — SWC is maintained by the Vercel team and used across the JavaScript ecosystem.

What the compiler handles

SWC strips TypeScript types and transforms JSX to React.createElement calls (or the automatic JSX runtime). This is the baseline transform applied to every file in your application.
Since Next.js 13, the SWC compiler minifies production output by default. This is 7x faster than Terser.
Starting with Next.js 15, minification cannot be customized via next.config.js. The swcMinify flag has been removed.
The compiler removes server-only code from client bundles and client-only code from server bundles using compile-time if/else branches that evaluate process.env.NODE_ENV and other build-time constants.
Source maps are generated for both client and server bundles, enabling accurate stack traces during development and in production error monitoring tools.

Supported transforms

Styled Components

Port of babel-plugin-styled-components. Adds server-side rendering support and display names for styled components.
module.exports = {
  compiler: {
    styledComponents: true,
  },
}
For advanced configuration:
module.exports = {
  compiler: {
    styledComponents: {
      displayName: true,    // adds display names (default: dev only)
      ssr: true,            // enables SSR support (default: true)
      fileName: true,       // includes filename in class names (default: true)
      minify: true,         // minifies template literals (default: true)
      transpileTemplateLiterals: true,
      pure: false,          // enables pure annotation for tree-shaking
      cssProp: true,        // enables the css prop
    },
  },
}

Emotion

Port of @emotion/babel-plugin. Adds source maps and auto-labeling to Emotion CSS-in-JS.
module.exports = {
  compiler: {
    emotion: {
      sourceMap: true,         // default: true in dev
      autoLabel: 'dev-only',   // 'never' | 'dev-only' | 'always'
      labelFormat: '[local]',  // '[local]' | '[filename]' | '[dirname]'
    },
  },
}

Relay

Compiles Relay GraphQL queries at build time:
module.exports = {
  compiler: {
    relay: {
      src: './',
      artifactDirectory: './__generated__',
      language: 'typescript',
      eagerEsModules: false,
    },
  },
}
Set artifactDirectory outside your pages/ directory. The relay compiler generates files next to source files, and files inside pages/ are treated as routes, which breaks production builds.

Remove React properties

Removes JSX properties matching a regex. Commonly used to strip data-test* attributes from production builds:
module.exports = {
  compiler: {
    // Remove properties matching the default regex: ^data-test
    reactRemoveProperties: true,

    // Or specify custom regexes (Rust regex syntax)
    // reactRemoveProperties: { properties: ['^data-custom$'] },
  },
}

Remove console calls

Strips console.* calls from application code (not node_modules):
module.exports = {
  compiler: {
    removeConsole: true,

    // Keep console.error
    // removeConsole: { exclude: ['error'] },
  },
}

Module transpilation

Transpiles and bundles dependencies from local packages (monorepos) or node_modules:
module.exports = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
}

Build-time variable replacement

Statically replaces variables at build time using the define option:
module.exports = {
  compiler: {
    define: {
      MY_VARIABLE: 'my-string',
      'process.env.MY_ENV_VAR': 'my-env-var',
    },
    // Server and edge only:
    defineServer: {
      MY_SERVER_VARIABLE: 'my-server-var',
    },
  },
}

Build lifecycle hooks

Run custom code after production compilation finishes, before type checking and static generation:
module.exports = {
  compiler: {
    runAfterProductionCompile: async ({ distDir, projectDir }) => {
      // Collect sourcemaps, notify error monitoring tools, etc.
      console.log('Build output at:', distDir)
    },
  },
}

Experimental features

SWC plugins

SWC supports experimental plugins written in WebAssembly:
module.exports = {
  experimental: {
    swcPlugins: [
      ['my-swc-plugin', { /* plugin options */ }],
    ],
  },
}
Each entry in swcPlugins is a tuple of the npm package name (or path to a .wasm binary) and a configuration object.

SWC trace profiling

Generate Chromium trace events to profile the compiler’s internal transforms:
module.exports = {
  experimental: {
    swcTraceProfiling: true,
  },
}
Trace files are written to .next/swc-trace-profile-{timestamp}.json. Open them in Perfetto or chrome://tracing.

Babel fallback

If your project has a .babelrc file, Next.js automatically falls back to Babel for transforming individual files. This ensures compatibility with existing applications that use custom Babel plugins. If you are using a custom Babel setup and want to migrate to the SWC compiler, remove .babelrc and replace any custom transforms with the SWC plugin API or one of the built-in transforms above.
Compilation with Babel active is ~17x slower than with SWC. Migrating to SWC is recommended for most applications.

Version history

VersionChanges
v15.0.0swcMinify flag removed; minification always uses SWC
v13.1.0Module transpilation and modularize imports stable
v13.0.0SWC minifier enabled by default
v12.3.0SWC minifier stable
v12.2.0SWC plugins experimental support added
v12.1.0Styled Components, Jest, Relay, and other transforms added
v12.0.0Next.js Compiler introduced

Build docs developers (and LLMs) love