Overview
SWC compiles TypeScript, JSX and modern JavaScript down to a chosen target, converts module formats and minifies output. It is a native Rust binary exposed to Node.js as @swc/core, so it is much faster than Babel on large codebases. It strips types but does not type-check; run tsc --noEmit separately. Next.js uses SWC internally, and Parcel and many Vite, Jest and webpack setups use it through plugins and loaders.
Packages: @swc/core (API), @swc/cli (the swc command), @swc/jest (Jest transformer), swc-loader (webpack), @swc/helpers (runtime helpers when externalHelpers is on).
Instructions
Install and compile
npm install -D @swc/core @swc/cli chokidar # chokidar only for -w
npx swc src/index.ts -o dist/index.js # one file
npx swc src -d dist --strip-leading-paths # directory -> dist/index.js (without the flag the output is dist/src/index.js)
npx swc src -d dist -w # watch
npx swc src -d dist -C module.type=commonjs # override a .swcrc key
.swcrc
{
"$schema": "https://swc.rs/schema.json",
"jsc": {
"parser": { "syntax": "typescript", "tsx": true, "decorators": true },
"transform": {
"react": { "runtime": "automatic" },
"decoratorVersion": "2022-03"
},
"target": "es2020"
},
"module": { "type": "es6" },
"sourceMaps": true
}
module.typeis one ofes6,commonjs,umd,amd,nodenext; SWC never rewrites import specifiers, so write the.jsextension yourself when the output runs as ESM on Node.jsc.targetandenv(browserslist targets,env.targets,env.mode: "usage"withenv.coreJs) are alternatives (setting both fails with "envandjsc.targetcannot be used together"): useenvfor browser support matrices,jsc.targetfor a fixed ES version.jsc.pathsplusjsc.baseUrlrewrite tsconfig-style path aliases at compile time.
Programmatic API
import { minify, transform } from "@swc/core";
const { code, map } = await transform(source, {
filename: "Greeting.tsx", // needed so .swcrc and the parser are chosen correctly
jsc: { parser: { syntax: "typescript", tsx: true }, transform: { react: { runtime: "automatic" } }, target: "es2020" },
module: { type: "es6" },
sourceMaps: true,
});
const small = await minify("function add(first, second) { return first + second }", { compress: true, mangle: true });
transformSync and minifySync exist for build tools that cannot await. Prefer the async versions: they run on the thread pool.
Minify
Either set "minify": true at the top level of .swcrc with options under jsc.minify, or call minify():
{ "minify": true, "jsc": { "minify": { "compress": { "drop_console": true, "passes": 2 }, "mangle": true } } }
There is no separate swc-minify command.
Jest
npm install -D jest @swc/core @swc/jest
// jest.config.js
module.exports = {
transform: {
"^.+\\.(t|j)sx?$": ["@swc/jest", {
jsc: { parser: { syntax: "typescript", tsx: true }, transform: { react: { runtime: "automatic" } } },
}],
},
};
If a .swcrc exists, @swc/jest reads it; passing inline options in the transform entry is the clearer route.
Examples
Example 1: Build a TypeScript library to ESM and CommonJS
Request: "Compile src to dist for both module systems, with source maps."
npx swc src -d dist/esm --strip-leading-paths -C module.type=es6 --source-maps
npx swc src -d dist/cjs --strip-leading-paths -C module.type=commonjs --source-maps
npx tsc --noEmit
Result: dist/esm/index.js and dist/cjs/index.js with .js.map files; the last command catches type errors because SWC does not.
Example 2: Minified production bundle step without console logs
Request: "Minify this React component and remove console.log."
With the .swcrc above extended by "minify": true and jsc.minify.compress.drop_console: true, npx swc src -d dist turns a component with console.log("render") into one line of mangled JavaScript using react/jsx-runtime with no console call.
Guidelines
- SWC does not type-check and does not emit
.d.tsin the default setup (the experimentaljsc.experimental.emitIsolatedDtsneeds explicit type annotations, as in TypeScript'sisolatedDeclarations); keeptscfor declarations and checks. - Without
--strip-leading-paths,swc src -d distwrites todist/src. - With
"minify": trueat the top level SWC minifies every output; keep it in a production-only config (npx swc src -d dist --config-file .swcrc.prod). isolatedModulesrules apply: re-exporting types needsexport type.- In Next.js, a custom
.babelrcturns SWC off for that app; remove it unless a Babel plugin is required. - Plugins are WebAssembly built against a specific
@swc/coreversion range; upgrade them together. - Speed-up figures vary by project; measure your own build instead of trusting headline multipliers.