SWC integration for Jest test runner providing fast TypeScript and JavaScript compilation during testing
npx @tessl/cli install tessl/npm-swc--jest@0.2.0@swc/jest provides SWC integration for the Jest test runner, offering fast TypeScript and JavaScript compilation during testing. It serves as a drop-in replacement for ts-jest or babel-jest with significantly faster compilation speeds, while supporting modern JavaScript features, TypeScript, JSX, and custom SWC configuration.
npm install -D jest @swc/core @swc/jest@swc/core (required)export = { createTransformer })const swcJest = require("@swc/jest");
const { createTransformer } = swcJest;For TypeScript projects:
import swcJest from "@swc/jest";
const { createTransformer } = swcJest;Configure Jest to use @swc/jest as a transformer:
// jest.config.js
module.exports = {
transform: {
'^.+\\.(t|j)sx?$': '@swc/jest',
},
};// jest.config.js
module.exports = {
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest', {
jsc: {
target: 'es2021',
parser: {
syntax: 'typescript',
tsx: true,
},
},
experimental: {
customCoverageInstrumentation: {
enabled: true,
},
},
}],
},
};Creates a Jest transformer that uses SWC for fast compilation of TypeScript and JavaScript files.
/**
* Creates a Jest transformer that uses SWC for compilation
* @param swcTransformOpts - SWC options with optional experimental coverage settings
* @returns Jest Transformer instance
*/
function createTransformer(
swcTransformOpts?: Options & {
experimental?: {
customCoverageInstrumentation?: CoverageInstrumentationOptions;
};
}
): Transformer;
interface CoverageInstrumentationOptions {
/** Enable custom coverage instrumentation */
enabled: boolean;
/** Coverage variable name (default: '__coverage__') */
coverageVariable?: string;
/** Compact output format */
compact?: boolean;
/** Report logic coverage */
reportLogic?: boolean;
/** Array of class method names to ignore during instrumentation */
ignoreClassMethods?: Array<string>;
/** Instrumentation logging configuration */
instrumentLog?: {
level: string;
enableTrace: boolean;
};
}The returned transformer implements the Jest Transformer interface with these methods:
interface Transformer {
/** Indicates whether the transformer can instrument code for coverage */
canInstrument: boolean;
/**
* Synchronously transforms source code using SWC
* Module type behavior: Uses 'commonjs' unless jestOptions.supportsStaticESM is true, then uses 'es6'
* @param src - Source code to transform
* @param filename - File path for the source
* @param jestOptions - Jest transformation options
* @returns Transformed code result
*/
process(
src: string,
filename: string,
jestOptions: TransformOptions
): TransformResult;
/**
* Asynchronously transforms source code using SWC
* Module type behavior: Always uses 'es6' module format for async transformations
* @param src - Source code to transform
* @param filename - File path for the source
* @param jestOptions - Jest transformation options
* @returns Promise resolving to transformed code result
*/
processAsync(
src: string,
filename: string,
jestOptions: TransformOptions
): Promise<TransformResult>;
/**
* Generates cache key for transformed files
* @param src - Source code
* @param filename - File path
* @param rest - Additional Jest transform parameters
* @returns SHA-1 hash string for caching
*/
getCacheKey(
src: string,
filename: string,
...rest: any[]
): string;
}
interface TransformOptions {
/** Whether Jest supports static ESM */
supportsStaticESM?: boolean;
/** Whether to instrument code for coverage */
instrument?: boolean;
}
interface TransformResult {
/** Transformed code */
code: string;
/** Source map (optional) */
map?: string | object;
}@swc/jest applies several automatic configuration behaviors when creating a transformer:
.swcrc in the current working directory if no options are provided to createTransformer()jsc.target is configured, automatically sets the target based on your Node.js versionjsc.transform.hidden.jest = true for Jest-specific optimizations (this flag enables SWC's Jest compatibility mode)sourceMaps: "inline" if not explicitly configuredjsc.baseUrl to an absolute path if specifiedcommonjs or es6) based on Jest's supportsStaticESM option, regardless of your SWC configurationConfiguration is loaded automatically from a .swcrc file in the project root when no options are provided:
{
"jsc": {
"target": "es2021",
"parser": {
"syntax": "typescript",
"tsx": true,
"decorators": true
},
"transform": {
"react": {
"runtime": "automatic"
}
}
},
"module": {
"type": "commonjs"
},
"sourceMaps": true
}When no explicit target is configured, @swc/jest automatically sets the jsc.target based on your Node.js version:
| Node Version | Default Target |
|---|---|
| 18+ | es2023 |
| 17 | es2022 |
| 15 | es2021 |
| 14 | es2020 |
| 13 | es2019 |
| <13 | es2018 |
Enable custom coverage instrumentation through SWC plugins:
// jest.config.js
module.exports = {
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest', {
experimental: {
customCoverageInstrumentation: {
enabled: true,
coverageVariable: '__coverage__',
compact: false,
reportLogic: true,
ignoreClassMethods: ['constructor'],
instrumentLog: {
level: 'info',
enableTrace: false,
},
},
},
}],
},
collectCoverage: true,
};For ESM (ECMAScript Module) support:
"type": "module" to package.json for JavaScript projects// jest.config.js
module.exports = {
preset: 'ts-jest/presets/default-esm',
extensionsToTreatAsEsm: ['.ts', '.tsx'],
transform: {
'^.+\\.(t|j)sx?$': '@swc/jest',
},
};cross-env NODE_OPTIONS=--experimental-vm-modules jestThe transformer accepts all standard SWC Options from @swc/core:
interface Options {
/** ECMAScript target version */
jsc?: {
target?: 'es3' | 'es5' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'es2023';
parser?: {
syntax: 'ecmascript' | 'typescript';
jsx?: boolean;
tsx?: boolean;
decorators?: boolean;
};
transform?: {
react?: {
runtime?: 'automatic' | 'classic';
pragma?: string;
pragmaFrag?: string;
};
};
baseUrl?: string;
};
/** Module system configuration */
module?: {
type?: 'commonjs' | 'umd' | 'amd' | 'es6';
};
/** Source map generation */
sourceMaps?: boolean | 'inline';
/** Environment preset */
env?: {
targets?: string | string[] | object;
};
}The package handles several error conditions with specific error messages:
jsonc-parser to provide detailed error information with line/column positions when .swcrc contains invalid JSONError("Could not parse major version from ${process.version}") if the Node.js version string cannot be parsedcreateTransformer() result in SWC-specific error messagesprocess() or processAsync() include filename contextExample error scenarios:
// Invalid .swcrc file
try {
const transformer = createTransformer(); // Will try to load .swcrc
} catch (error) {
console.error('Configuration error:', error.message);
// Example: "Error parsing /path/to/.swcrc: Unexpected token..."
}
// Invalid SWC options
try {
const transformer = createTransformer({
jsc: { target: 'invalid-target' }
});
} catch (error) {
console.error('SWC configuration error:', error.message);
}
// Node.js version parsing failure (rare)
// Would occur if process.version is malformedThe coverage instrumentation feature automatically handles plugin conflicts:
swc-plugin-coverage-instrument is already configured in jsc.experimental.plugins, it won't be added againjestOptions.instrument is true and customCoverageInstrumentation.enabled is true