esbuild can dramatically speed up your Jest unit tests by replacing Babel with its own lightning-fast transpilation.

Here’s how to set it up:

First, install the necessary packages:

npm install --save-dev jest esbuild-jest
# or
yarn add --dev jest esbuild-jest

Next, configure Jest to use esbuild-jest as a transformer. Create or modify your jest.config.js (or jest.config.ts) file:

// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'esbuild-jest',
  },
  // ... other Jest configurations
};

This tells Jest that for any files ending in .js, .jsx, .ts, or .tsx, it should use the esbuild-jest transformer. esbuild-jest will then use esbuild under the hood to transpile your code.

Now, let’s see it in action. Imagine you have a simple JavaScript file math.js:

// math.js
export function add(a, b) {
  return a + b;
}

And a corresponding test file math.test.js:

// math.test.js
import { add } from './math';

describe('add', () => {
  test('should return the sum of two numbers', () => {
    expect(add(2, 3)).toBe(5);
  });
});

When you run jest, esbuild-jest will intercept the .js files. It will use esbuild to quickly transform the ES module syntax (import, export) into CommonJS (require, module.exports), which Jest understands natively.

The key benefit here is speed. esbuild is written in Go and is incredibly fast. It compiles down to native code, giving it a significant performance advantage over JavaScript-based bundlers like Babel. For projects with many tests or complex transpilation needs (like TypeScript or JSX), this can translate to minutes saved per test run.

The esbuild-jest package handles the integration seamlessly. It exposes a Jest transformer interface that Jest knows how to use. When Jest encounters a file matching the transform pattern, it invokes esbuild-jest, which in turn invokes esbuild to do the actual transpilation.

You can also configure esbuild’s behavior through Jest’s configuration. For example, to specify a target environment for your transpiled code:

// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': [
      'esbuild-jest',
      {
        target: 'es2017', // Or 'esnext', 'node14', etc.
      },
    ],
  },
  // ... other Jest configurations
};

Setting target: 'es2017' means that esbuild will transpile your code down to features available in ES2017. This is useful for ensuring compatibility with your target Node.js version or browser environment, even though Jest typically runs in a Node.js environment.

For TypeScript projects, the setup is identical, and esbuild will handle the TypeScript compilation:

npm install --save-dev typescript
# or
yarn add --dev typescript
// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': 'esbuild-jest',
  },
  // ... other Jest configurations
};

esbuild-jest automatically infers that if you’re using TypeScript, it should use esbuild’s TypeScript transpilation capabilities. You don’t need to explicitly configure tsconfig.json for Jest’s transpilation step, as esbuild will handle it directly.

The real magic happens when you have a large codebase. Babel’s traversal of the AST and its plugin system, while powerful, can become a bottleneck. esbuild, with its single-pass compilation and highly optimized algorithms, bypasses much of this overhead. It doesn’t rely on a plugin architecture in the same way Babel does; its features are built-in and highly performant.

One subtle but significant advantage is esbuild’s handling of source maps. By default, esbuild-jest generates source maps that Jest can use for accurate error reporting. This means that when a test fails, the stack trace will point to the original source file, not the transpiled output, making debugging much smoother.

If you encounter issues with specific syntax or features not being transpiled correctly, it’s usually because esbuild’s capabilities are slightly different from Babel’s. However, for most common JavaScript and TypeScript features, it’s a drop-in replacement. The esbuild-jest package is actively maintained and tries to bridge any remaining gaps.

The next challenge you’ll likely face is optimizing your test setup further, perhaps by exploring Jest’s caching mechanisms or parallel test execution, and seeing how esbuild’s speed complements those features.

Want structured learning?

Take the full Esbuild course →