← Back to DevBytes

SWC Performance: Optimization Techniques and Benchmarks

Introduction to SWC Performance

SWC (Speedy Web Compiler) is a Rust-based platform for compilation, bundling, and minification of JavaScript and TypeScript code. Built from the ground up to leverage Rust's zero-cost abstractions and multi-threading capabilities, SWC has emerged as one of the fastest JavaScript toolchains available today. In this tutorial, we will explore what makes SWC performant, how to optimize its usage in your projects, and how to benchmark it against alternatives like Babel.

What Is SWC?

SWC is an extensible JavaScript and TypeScript compiler written in Rust. It can be used for transpilation, minification, bundling, and even type checking. Because it compiles to native code and uses parallel processing, SWC routinely outperforms JavaScript-based tools by an order of magnitude on single-core benchmarks and even more on multi-core workloads.

Why Performance Matters

Modern web development workflows depend on fast feedback loops. Slow transpilation and bundling directly impact developer experience, CI/CD pipeline duration, and deployment frequency. When your codebase grows to hundreds of thousands of lines, a Babel-based pipeline can take minutes to compile, while SWC often completes the same work in seconds. This performance gap translates into real productivity gains and cost savings, especially in large engineering organizations.

How SWC Achieves High Performance

SWC's speed is not accidental. It results from several deliberate architectural decisions that differentiate it from JavaScript-based compilers.

Setting Up SWC in Your Project

Before optimizing, you need a working SWC setup. The most common entry point is the @swc/core package, which provides Node.js bindings to the native Rust binary.

Installing SWC

npm install --save-dev @swc/core @swc/cli

After installation, you can invoke SWC directly from the command line or programmatically from Node.js scripts.

Basic Configuration

SWC uses a .swcrc file for configuration. Here is a minimal example that transpiles TypeScript and modern JavaScript syntax down to ES2015:

{
  "$schema": "https://swc.rs/schema.json",
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "target": "es2015",
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    }
  },
  "minify": true
}

Programmatic Usage

For build scripts and custom tooling, you can call SWC directly from Node.js. This gives you fine-grained control over input, output, and transformation options.

const swc = require("@swc/core");

async function compile() {
  const output = await swc.transformFile("./src/index.ts", {
    jsc: {
      parser: { syntax: "typescript" },
      target: "es2020"
    },
    minify: true
  });

  console.log(output.code);
}

compile();

Optimization Techniques

While SWC is fast out of the box, you can extract even more performance by applying the following techniques.

1. Enable Parallel Processing

When using SWC with webpack, ensure you configure swc-loader to run in parallel mode. This allows multiple files to be processed simultaneously across worker threads.

module.exports = {
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        use: {
          loader: "swc-loader",
          options: {
            jsc: {
              parser: { syntax: "typescript", tsx: true },
              transform: { react: { runtime: "automatic" } }
            }
          }
        }
      }
    ]
  }
};

Webpack automatically parallelizes loaders when configured with multiple workers, but you can also use thread-loader for additional control.

2. Use Caching Aggressively

Caching is one of the most effective optimizations. SWC itself is stateless, but the surrounding build system can cache results. In webpack 5, enable persistent caching:

module.exports = {
  cache: {
    type: "filesystem",
    buildDependencies: {
      config: [__filename]
    }
  }
};

This allows subsequent builds to skip recompiling unchanged files entirely, reducing build times from minutes to seconds in incremental scenarios.

3. Choose the Right Target

The target option determines which syntax transformations SWC applies. Setting it too low forces unnecessary transformations. If your users run modern browsers, target es2020 or higher to skip transpiling features like arrow functions and async/await.

{
  "jsc": {
    "target": "es2020"
  }
}

4. Minify with SWC Instead of Terser

SWC includes a built-in minifier that is significantly faster than Terser. In webpack, replace TerserPlugin with SWC's minifier:

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        minify: TerserPlugin.swcMinify,
        terserOptions: {}
      })
    ]
  }
};

This single change can reduce minification time by up to 20x on large bundles.

5. Disable Unnecessary Transformations

Review your .swcrc and disable any transformations you do not need. For example, if you are not using decorators, do not enable them. Each transformation adds overhead to the AST traversal.

{
  "jsc": {
    "transform": {
      "legacyDecorator": false,
      "decoratorMetadata": false
    }
  }
}

6. Use SWC for Bundling with spack

SWC ships with its own bundler called spack. For projects that do not need webpack's extensive plugin ecosystem, spack offers faster end-to-end builds.

const { Configuration } = require("@swc/spack");

module.exports = {
  entry: {
    main: "./src/index.ts"
  },
  output: {
    path: __dirname + "/dist"
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: {
          loader: "swc-loader"
        }
      }
    ]
  }
};

Benchmarking SWC

To validate performance claims, you should benchmark SWC against your existing toolchain. A simple benchmark measures compilation time for a representative codebase.

Writing a Benchmark Script

const swc = require("@swc/core");
const babel = require("@babel/core");
const fs = require("fs");
const path = require("path");

const files = fs.readdirSync("./src")
  .filter(f => f.endsWith(".ts"))
  .map(f => path.join("./src", f));

async function benchmarkSwc() {
  const start = performance.now();
  for (const file of files) {
    await swc.transformFile(file, {
      jsc: { parser: { syntax: "typescript" }, target: "es2020" }
    });
  }
  return performance.now() - start;
}

function benchmarkBabel() {
  const start = performance.now();
  for (const file of files) {
    babel.transformFileSync(file, {
      presets: ["@babel/preset-typescript"]
    });
  }
  return performance.now() - start;
}

(async () => {
  const swcTime = await benchmarkSwc();
  const babelTime = benchmarkBabel();
  console.log(`SWC:   ${swcTime.toFixed(2)} ms`);
  console.log(`Babel: ${babelTime.toFixed(2)} ms`);
  console.log(`Speedup: ${(babelTime / swcTime).toFixed(2)}x`);
})();

Typical Benchmark Results

On a mid-size project with 500 TypeScript files, you can expect results similar to the following. Actual numbers vary based on hardware, file complexity, and configuration.

SWC:   1240.55 ms
Babel: 18650.22 ms
Speedup: 15.04x

For minification, the gap is even wider. Minifying a 2 MB bundle with Terser might take 8 seconds, while SWC completes the same task in under 400 milliseconds.

Benchmarking Best Practices

Integrating SWC with Popular Frameworks

Next.js

Next.js 12 and later use SWC by default for compilation and minification. No configuration is required. If you are on an older version, upgrading to the latest Next.js automatically gives you SWC's performance benefits.

Vite

Vite uses esbuild for development transforms, but you can use SWC for production builds via the vite-plugin-swc plugin:

import { defineConfig } from "vite";
import swc from "vite-plugin-swc";

export default defineConfig({
  plugins: [swc()]
});

Jest

Replace ts-jest or babel-jest with @swc/jest for faster test transpilation:

module.exports = {
  transform: {
    "^.+\\.(t|j)sx?$": "@swc/jest"
  }
};

This change alone can reduce Jest startup time by 50% or more on large projects.

Best Practices Summary

Conclusion

SWC represents a paradigm shift in JavaScript tooling, proving that native compilation and thoughtful architecture can deliver dramatic performance improvements over traditional Node.js-based compilers. By understanding how SWC achieves its speed and applying the optimization techniques covered in this tutorial, you can significantly reduce build times, improve developer experience, and lower CI costs. Whether you adopt SWC through Next.js, webpack, Vite, or directly via its API, the combination of parallel processing, aggressive caching, and native minification makes it one of the most impactful upgrades available to modern web development teams. Start by benchmarking your current pipeline, migrate incrementally, and measure the results to unlock the full potential of SWC in your projects.

— Ad —

Google AdSense will appear here after approval

← Back to all articles