Overview

Use SWC for new JavaScript and TypeScript projects. It is 20 to 70 times faster than Babel on large codebases, supports TypeScript and JSX natively, and is the default transform in Next.js, Vite, and Bun. Use Babel only when you depend on plugins that SWC does not implement: Babel macros, babel-plugin-transform-decorators-legacy in its exact form, or custom company-specific AST transforms. See vite-vs-webpack for the bundler context.

When SWC wins

SWC is the right transpiler for nearly all new projects.

  • Speed: SWC is written in Rust and compiles TypeScript and JSX in a single pass without type-checking. A 500-file project that takes 8 seconds with Babel compiles in under 400 ms with SWC. This difference compounds on watch rebuilds.
  • TypeScript and JSX: SWC strips types and transpiles JSX natively. No @babel/preset-typescript or @babel/preset-react needed.
  • Next.js default since 12: Next.js ships with SWC and disables it only if a custom .babelrc is present. Removing the Babel config restores the fast path.
  • Jest via @swc/jest: replace babel-jest and ts-jest with @swc/jest for test transforms. Watch-mode re-runs feel instant.
  • @swc/core API: programmatic transforms are straightforward. Plugins exist for common patterns.
// .swcrc
{
  "jsc": {
    "parser": { "syntax": "typescript", "tsx": true },
    "target": "es2020"
  },
  "module": { "type": "commonjs" }
}

When Babel wins

Babel remains the correct choice when specific plugins are real dependencies.

  • Babel macros (babel-plugin-macros): compile-time code generation libraries like linaria, twin.macro, and some CSS-in-JS tools rely on Babel macros. SWC does not support the Babel macro protocol.
  • babel-plugin-transform-decorators-legacy: some ORMs and frameworks (TypeORM, older NestJS configs) require this exact plugin’s behavior. SWC’s decorator support follows the TC39 proposal, which behaves differently.
  • Custom AST plugins: teams with internal Babel plugins for code transforms (feature flags, i18n extraction) need those plugins ported or rewritten before switching.
  • Partial coverage: if the codebase uses @babel/plugin-proposal-pipeline-operator or other Stage 2/3 proposals, check SWC’s plugin list first.

Trade-offs at a glance

DimensionSWCBabel
Speed20 to 70x faster than BabelBaseline; slower on large codebases
LanguageRustJavaScript
TypeScript supportNative strip (no type-check)Via @babel/preset-typescript
JSX supportNativeVia @babel/preset-react
Plugin ecosystemGrowing; covers common casesMature; thousands of plugins
Babel macrosNot supportedFirst-class
DecoratorsTC39 proposal semanticsLegacy and proposal semantics
Next.js integrationDefault since Next 12Opt-in via .babelrc (disables SWC)
Jest transform@swc/jestbabel-jest
Custom AST transformsSWC plugin API (Rust or JS WASM)Plain JavaScript plugins
Config complexityLow; .swcrc is conciseModerate; multiple presets and plugins

Migration cost

Babel to SWC migration is usually straightforward for standard configurations.

  • Remove babel-jest, @babel/core, and presets. Add @swc/core and @swc/jest.
  • Create a minimal .swcrc with parser settings, target, and module type.
  • Run the test suite. Most failures are from macro-dependent code or decorator edge cases. Fix or exclude those files.
  • For Next.js: simply delete .babelrc. Next.js detects the absence and enables SWC automatically.
  • Effort: half a day for a project with no macros or legacy decorator patterns. Budget additional time per macro-dependent library, since those require finding a non-macro alternative or maintaining a Babel transform just for that file.

SWC to Babel is a regression. Do not do it unless forced by a specific plugin requirement.

Recommendation

  • New project: SWC. Set it as the Jest transform and the Vite/bundler transform from the start.
  • Next.js project: ensure no .babelrc is present. SWC is the default and should stay the default.
  • Project using Babel macros: evaluate whether the macro library has a non-macro alternative (many do). If not, stay on Babel for that specific transform and use SWC elsewhere.
  • TypeORM or legacy decorator project: check SWC’s legacyDecorator option; it covers many cases. Test against your actual entity decorators before committing.