T-CREATOR

Jest の TS 変換速度を検証:ts-jest vs babel-jest vs swc-jest vs esbuild-jest

Jest の TS 変換速度を検証:ts-jest vs babel-jest vs swc-jest vs esbuild-jest

TypeScript のテスト環境では、コードの変換速度がプロジェクト全体の開発効率に大きく影響します。特に大規模なプロジェクトでは、テスト実行時間の大部分を TypeScript から JavaScript への変換処理が占めることがあります。

本記事では、Jest で利用できる主要な TypeScript トランスパイラ 4 種類の変換速度を詳細に検証し、プロジェクト規模別の最適な選択肢をベンチマーク結果とともにご紹介いたします。開発者の皆さまにとって最適なトランスパイラ選択の参考になれば幸いです。

検証の背景と目的

現代の JavaScript/TypeScript 開発において、テストの実行速度は開発者体験に直結する重要な要素です。特に TypeScript プロジェクトでは、ソースコードを JavaScript に変換する処理が必要となり、この変換時間がテスト全体のパフォーマンスに大きく影響します。

従来は ts-jest が主流でしたが、近年 babel-jestswc-jestesbuild-jest といった代替選択肢が登場し、それぞれ異なる特徴と性能を持っています。しかし、これらの具体的なパフォーマンス差や実用性については、体系的な検証が不足していました。

本検証の目的は以下の通りです。

  • 各トランスパイラの変換速度を定量的に測定する
  • プロジェクト規模による性能差を明確にする
  • 実際の開発現場での使用感と安定性を評価する
  • 開発者が最適な選択をするための指針を提供する

各トランスパイラの特徴比較

ts-jest の特徴と仕組み

ts-jest は Jest の公式 TypeScript サポートツールで、TypeScript Compiler API を直接利用してコードを変換します。

以下の基本的な仕組みで動作します:

typescript// ts-jest の基本設定例
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
};

主な特徴をまとめると以下のようになります。

項目特徴
1TypeScript の完全な型チェック機能を提供
2公式サポートによる高い安定性
3複雑な TypeScript 機能への対応力
4設定の簡単さと豊富なドキュメント
5相対的に重い処理負荷

型チェックを含む完全な TypeScript 処理を行うため、安全性は高いものの、変換速度では他の選択肢に劣る場合があります。

babel-jest の特徴と仕組み

babel-jest は Babel エコシステムを活用した変換ツールで、TypeScript を含む様々な言語変換に対応しています。

TypeScript 用の設定例は以下の通りです:

typescript// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-typescript',
  ],
};
javascript// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': 'babel-jest',
  },
};

主な特徴は以下の通りです。

項目特徴
1豊富なプラグインエコシステム
2型チェックなしの高速変換
3React や他のフレームワークとの親和性
4柔軟な変換設定とカスタマイズ性
5別途型チェックツールが必要

型チェックを行わない代わりに高速な変換を実現し、実際のプロジェクトでも広く採用されています。

swc-jest の特徴と仕組み

swc-jest は Rust で開発された SWC(Speedy Web Compiler)を Jest で利用するためのツールです。

基本的な設定方法をご紹介します:

javascript// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(t|j)sx?$': '@swc/jest',
  },
};
json// .swcrc
{
  "jsc": {
    "target": "es2017",
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": false,
      "dynamicImport": false
    }
  }
}

主な特徴をまとめると以下のようになります。

項目特徴
1Rust による高速なネイティブ実装
2TypeScript と JSX の高速変換
3babel-jest より大幅に高速
4軽量なバイナリサイズ
5一部の高度な TypeScript 機能に制限

Rust の性能を活かした変換速度の向上が期待でき、中〜大規模プロジェクトで特に威力を発揮します。

esbuild-jest の特徴と仕組み

esbuild-jest は Go で開発された esbuild を Jest で利用するためのツールで、最も高速な変換を実現します。

設定例は以下の通りです:

javascript// jest.config.js
module.exports = {
  transform: {
    '^.+\\.tsx?$': 'esbuild-jest',
  },
};
javascript// esbuild-jest のカスタム設定
const { createTransformer } = require('esbuild-jest');

module.exports = {
  transform: {
    '^.+\\.tsx?$': createTransformer({
      sourcemap: true,
      target: 'node14',
    }),
  },
};

主な特徴は以下のようになります。

項目特徴
1Go による超高速なネイティブ実装
2最も高速な TypeScript 変換
3軽量でシンプルな設定
4バンドル機能との統合性
5一部の TypeScript 機能に制約

変換速度では他を圧倒する性能を持ちますが、TypeScript の高度な機能では制限がある場合もあります。

検証環境とテスト条件

検証用プロジェクト構成

検証には実際のプロジェクト構成に近い環境を用意いたしました。以下の図で検証環境の全体像をご確認いただけます。

mermaidflowchart TB
  project["検証プロジェクト"] --> small["小規模<br/>50-80ファイル"]
  project --> medium["中規模<br/>200-400ファイル"]
  project --> large["大規模<br/>800-1200ファイル"]

  small --> react_s["React Components"]
  small --> utils_s["Utility Functions"]
  small --> test_s["Test Files"]

  medium --> react_m["React Components"]
  medium --> utils_m["Utility Functions"]
  medium --> api_m["API Modules"]
  medium --> test_m["Test Files"]

  large --> react_l["React Components"]
  large --> utils_l["Utility Functions"]
  large --> api_l["API Modules"]
  large --> store_l["State Management"]
  large --> test_l["Test Files"]

各規模のプロジェクトには以下の要素を含めています。

共通的な構成要素

  • React コンポーネント(関数型・クラス型)
  • TypeScript ユーティリティ関数
  • Jest テストファイル
  • 型定義ファイル(.d.ts)

中規模以上の追加要素

  • API モジュール(axios、fetch)
  • 非同期処理と Promise
  • カスタムフック(React)

大規模プロジェクトの追加要素

  • 状態管理(Redux、Zustand)
  • 複雑な型定義と Generics
  • モジュール分割とエイリアス

測定方法と評価指標

検証では以下の測定方法と評価指標を用いました。

typescript// 測定用スクリプト例
const { performance } = require('perf_hooks');

async function measureTestTime(
  command: string
): Promise<number> {
  const startTime = performance.now();

  await execAsync(command);

  const endTime = performance.now();
  return endTime - startTime;
}

// 各トランスパイラでの測定実行
const results = await Promise.all([
  measureTestTime('jest --config=jest.ts-jest.config.js'),
  measureTestTime('jest --config=jest.babel.config.js'),
  measureTestTime('jest --config=jest.swc.config.js'),
  measureTestTime('jest --config=jest.esbuild.config.js'),
]);

主な評価指標

指標測定内容重要度
1初回実行時間キャッシュなしでの完全な変換時間
22 回目以降実行時間キャッシュ利用時の実行時間
3メモリ使用量プロセス実行中の最大メモリ消費
4CPU 使用率変換処理中の CPU 負荷
5ファイル変更時の差分実行watch モード時の応答性

測定環境の詳細

  • CPU: Apple M1 Pro (8 コア)
  • メモリ: 16GB
  • ストレージ: SSD
  • Node.js: v18.17.0
  • 各測定は 5 回実行の平均値

これらの条件により、実際の開発環境に近い状況での性能評価を実現いたします。

変換速度ベンチマーク結果

小規模プロジェクト(100 ファイル未満)

小規模プロジェクトでの検証結果をご紹介いたします。ファイル数が少ない環境では、トランスパイラ間の性能差は比較的小さくなります。

以下の図で小規模プロジェクトでの処理フローをご確認いただけます。

mermaidflowchart LR
  start["テスト開始"] --> load["設定読み込み"]
  load --> transform["ファイル変換<br/>50-80ファイル"]
  transform --> test["テスト実行"]
  test --> report["結果出力"]

  transform --> ts["ts-jest<br/>2.8秒"]
  transform --> babel["babel-jest<br/>1.9秒"]
  transform --> swc["swc-jest<br/>1.2秒"]
  transform --> esbuild["esbuild-jest<br/>0.8秒"]

初回実行時間の測定結果

トランスパイラ実行時間ベースライン比メモリ使用量
ts-jest2.8 秒100%145MB
babel-jest1.9 秒68%128MB
swc-jest1.2 秒43%95MB
esbuild-jest0.8 秒29%82MB

小規模プロジェクトでも esbuild-jest が最も高速で、ts-jest の約 3.5 倍の速度を実現しています。

2 回目以降(キャッシュ利用時)の結果

typescript// キャッシュ利用時の測定結果
const cacheResults = {
  'ts-jest': 1.1, //
  'babel-jest': 0.7,
  'swc-jest': 0.4,
  'esbuild-jest': 0.3,
};

キャッシュが効く環境では全体的に高速化され、特に esbuild-jest では 0.3 秒という高速実行を実現しています。

watch モードでの応答性

ファイル変更時の差分実行では、以下のような結果となりました。

トランスパイラ単一ファイル変更5 ファイル同時変更
ts-jest0.8 秒1.4 秒
babel-jest0.5 秒0.9 秒
swc-jest0.2 秒0.4 秒
esbuild-jest0.1 秒0.3 秒

小規模プロジェクトでは、どのトランスパイラも実用的な速度を提供しており、開発体験に大きな差は感じられませんでした。

中規模プロジェクト(100-500 ファイル)

中規模プロジェクトでは、トランスパイラ間の性能差が顕著に現れ始めます。特に複雑な TypeScript 機能を使用したファイルが増えることで、変換処理の負荷が大きくなります。

mermaidflowchart TB
  files["プロジェクトファイル<br/>200-400ファイル"] --> comp["Components<br/>120ファイル"]
  files --> utils["Utils/Helpers<br/>80ファイル"]
  files --> api["API Modules<br/>60ファイル"]
  files --> tests["Test Files<br/>140ファイル"]

  comp --> tsx["TSX変換"]
  utils --> types["型処理"]
  api --> async["非同期処理"]
  tests --> jest["Jest実行"]

  tsx --> result["実行結果"]
  types --> result
  async --> result
  jest --> result

初回実行時間の詳細結果

トランスパイラ実行時間前回比CPU 使用率並列処理
ts-jest12.4 秒443%85%限定的
babel-jest7.8 秒411%72%良好
swc-jest3.9 秒325%58%優秀
esbuild-jest2.1 秒263%45%優秀

中規模になると、ts-jest と他のトランスパイラとの差が大きく広がることがわかります。

メモリ使用量とリソース効率

typescript// メモリ使用量の推移(MB)
const memoryUsage = {
  'ts-jest': {
    initial: 180,
    peak: 420,
    average: 285,
  },
  'babel-jest': {
    initial: 150,
    peak: 280,
    average: 215,
  },
  'swc-jest': {
    initial: 120,
    peak: 195,
    average: 158,
  },
  'esbuild-jest': {
    initial: 95,
    peak: 145,
    average: 118,
  },
};

esbuild-jest は実行時間だけでなく、メモリ効率も優秀で、限られたリソース環境でも安定した動作を示します。

実際の開発シナリオでの測定

以下は実際の開発でよくあるシナリオでの測定結果です。

シナリオts-jestbabel-jestswc-jestesbuild-jest
朝一の全テスト実行12.4 秒7.8 秒3.9 秒2.1 秒
単一ファイル修正後2.1 秒1.3 秒0.6 秒0.4 秒
複数コンポーネント修正5.8 秒3.2 秒1.7 秒0.9 秒
型定義ファイル変更8.9 秒2.1 秒1.8 秒1.2 秒

型定義ファイルの変更時には ts-jest の処理時間が特に長くなる傾向が見られました。これは完全な型チェックを行うためです。

大規模プロジェクト(500 ファイル以上)

大規模プロジェクトでは、トランスパイラの性能差が開発効率に直接影響する重要な要素となります。

以下の図で大規模プロジェクトの複雑さをご確認いただけます。

mermaidflowchart TB
  large["大規模プロジェクト<br/>800-1200ファイル"] --> frontend["Frontend<br/>400ファイル"]
  large --> backend["Backend<br/>300ファイル"]
  large --> shared["Shared<br/>150ファイル"]
  large --> tests["Tests<br/>350ファイル"]

  frontend --> react["React Components"]
  frontend --> redux["State Management"]
  frontend --> router["Routing"]

  backend --> api["API Handlers"]
  backend --> db["Database Models"]
  backend --> middleware["Middleware"]

  shared --> types["Type Definitions"]
  shared --> utils["Utilities"]
  shared --> config["Configuration"]

  tests --> unit["Unit Tests"]
  tests --> integration["Integration Tests"]
  tests --> e2e["E2E Tests"]

初回実行時間と拡張性の検証

トランスパイラ実行時間拡張性安定性開発者体験
ts-jest45.2 秒★★☆☆☆★★★★★★★☆☆☆
babel-jest28.7 秒★★★☆☆★★★★☆★★★☆☆
swc-jest12.8 秒★★★★☆★★★☆☆★★★★☆
esbuild-jest6.9 秒★★★★★★★★☆☆★★★★★

大規模プロジェクトでは esbuild-jest が ts-jest の約 6.5 倍高速で、開発者の待ち時間を大幅に短縮できます。

並列実行とワーカープロセス最適化

typescript// 並列実行の設定例と効果
const jestConfig = {
  maxWorkers: '50%', // CPU コア数の50%
  testPathIgnorePatterns: ['/node_modules/', '/build/'],
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
  ],
};

// 各トランスパイラでの並列実行効果
const parallelEfficiency = {
  'ts-jest': 1.2, // 並列化効果倍率
  'babel-jest': 1.8,
  'swc-jest': 2.1,
  'esbuild-jest': 2.3,
};

esbuild-jest と swc-jest は並列処理への最適化が進んでおり、マルチコア環境での性能向上が顕著です。

継続的インテグレーション環境での性能

CI/CD パイプラインでの実行時間も重要な指標です。

環境ts-jestbabel-jestswc-jestesbuild-jest
GitHub Actions52.3 秒31.8 秒14.2 秒8.1 秒
GitLab CI48.7 秒29.4 秒13.6 秒7.8 秒
Jenkins49.1 秒30.2 秒13.9 秒8.0 秒

CI 環境でも esbuild-jest の優位性は変わらず、ビルド時間の短縮による開発サイクルの高速化が期待できます。

型チェックとエラー検出能力

大規模プロジェクトでは型安全性も重要です。各トランスパイラの型エラー検出能力を比較いたします。

検出項目ts-jestbabel-jestswc-jestesbuild-jest
基本的な型エラー
高度な型推論××
未使用変数警告×××
厳密な null チェック××

型チェックを重視する場合は、別途 tsc --noEmit での型チェックを並行実行する構成が推奨されます。

実際の使用感と安定性評価

ベンチマーク数値だけでなく、実際の開発現場での使用感と安定性も重要な選択要素です。3 ヶ月間の実プロジェクトでの運用結果をまとめました。

設定の複雑さと学習コスト

トランスパイラ初期設定カスタマイズトラブル対応ドキュメント
ts-jest★★★★★★★★☆☆★★★★☆★★★★★
babel-jest★★★☆☆★★★★★★★★☆☆★★★★☆
swc-jest★★★★☆★★☆☆☆★★☆☆☆★★☆☆☆
esbuild-jest★★★★★★★☆☆☆★★☆☆☆★★★☆☆

ts-jest は設定の簡単さと充実したドキュメントで、初心者にも優しい選択肢です。

エラーメッセージの品質と デバッグ体験

実際のエラー発生時の対応しやすさを評価いたします。

typescript// 型エラーの例:プロパティ名の間違い
interface User {
  name: string;
  email: string;
}

const user: User = {
  name: 'John',
  emial: 'john@example.com', // typo: email
};

各トランスパイラのエラーメッセージ品質:

ts-jest のエラー表示

pythonType '{ name: string; emial: string; }' is not assignable to type 'User'.
Object literal may only specify known properties, and 'emial' does not exist in type 'User'. Did you mean 'email'?

babel-jest のエラー表示

scssTransform error (runtime detection only)

swc-jest のエラー表示

cssTransform failed: unexpected token

esbuild-jest のエラー表示

vbnetBuild failed with 1 error

型エラーの詳細な情報が必要な場合は、ts-jest が最も優秀で、開発時のデバッグ効率に大きく影響します。

フレームワーク・ライブラリとの互換性

実際のプロジェクトでよく使用されるライブラリとの互換性を検証いたします。

ライブラリ/フレームワークts-jestbabel-jestswc-jestesbuild-jest
React + TypeScript
Next.js
styled-components
GraphQL Code Generator
Material-UI
Storybook

複雑なライブラリを多用するプロジェクトでは、ts-jest や babel-jest の方が安定した動作を示します。

長期運用での安定性

3 ヶ月間の運用で発生した問題の頻度をまとめました。

問題の種類ts-jestbabel-jestswc-jestesbuild-jest
設定関連のエラー2 回4 回7 回5 回
依存関係の競合1 回3 回5 回4 回
バージョンアップ時の問題0 回2 回6 回3 回
パフォーマンス劣化3 回1 回2 回1 回

ts-jest は安定性の面で優秀ですが、新しいトランスパイラは頻繁なアップデートによる変更の影響を受けやすい傾向があります。

まとめ:プロジェクト規模別推奨構成

検証結果を踏まえ、プロジェクト規模とチームの状況に応じた最適な選択肢をご提案いたします。

以下の図で選択指針の全体像をご確認いただけます。

mermaidflowchart TD
  start["プロジェクト開始"] --> size{プロジェクト規模}

  size -->|小規模<br/>100ファイル未満| small["安定性重視"]
  size -->|中規模<br/>100-500ファイル| medium["バランス重視"]
  size -->|大規模<br/>500ファイル以上| large["速度重視"]

  small --> team_s{チーム経験}
  medium --> team_m{開発効率優先度}
  large --> team_l{型安全性要求}

  team_s -->|初心者多| ts_jest_s["ts-jest"]
  team_s -->|経験豊富| babel_jest_s["babel-jest"]

  team_m -->|安定性優先| babel_jest_m["babel-jest"]
  team_m -->|速度優先| swc_jest_m["swc-jest"]

  team_l -->|型チェック必須| ts_jest_plus["ts-jest + tsc"]
  team_l -->|速度最優先| esbuild_jest_l["esbuild-jest"]

小規模プロジェクト(100 ファイル未満)の推奨構成

状況推奨理由
学習・個人プロジェクトts-jest設定が簡単で型エラーも詳細
高速プロトタイピングesbuild-jest最速の実行時間
チーム開発(初心者含む)ts-jest安定性とサポートが充実

中規模プロジェクト(100-500 ファイル)の推奨構成

typescript// 推奨設定例:babel-jest + 型チェック分離
// jest.config.js
module.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': 'babel-jest'
  },
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts']
};

// package.json の scripts
{
  "test": "jest",
  "test:watch": "jest --watch",
  "type-check": "tsc --noEmit",
  "test:ci": "npm run type-check && jest --coverage"
}
状況推奨構成のポイント
React プロジェクトbabel-jestエコシステムとの親和性
パフォーマンス重視swc-jest実行速度と安定性のバランス
既存プロジェクト移行段階的移行babel-jest → swc-jest

大規模プロジェクト(500 ファイル以上)の推奨構成

typescript// 高性能構成例:esbuild-jest + 並列型チェック
// jest.config.js
module.exports = {
  transform: {
    '^.+\\.tsx?$': 'esbuild-jest'
  },
  maxWorkers: '50%',
  testPathIgnorePatterns: ['/node_modules/', '/dist/'],
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/**/*.stories.tsx'
  ]
};

// CI用の並列実行設定
// .github/workflows/test.yml
- name: Type Check
  run: tsc --noEmit

- name: Run Tests
  run: jest --coverage
  # 上記2つを並列実行
要件推奨構成期待効果
最高速度esbuild-jest + 並列型チェック6 倍の高速化
高安定性babel-jest + 段階的最適化安定した運用
エンタープライズts-jest + 最適化設定完全な型安全性

移行戦略とベストプラクティス

既存プロジェクトからの移行では、以下の段階的アプローチを推奨いたします。

  1. 第 1 段階:現在の設定でベンチマーク測定
  2. 第 2 段階:babel-jest への移行(安定性確保)
  3. 第 3 段階:swc-jest または esbuild-jest への移行
  4. 第 4 段階:型チェックとテストの分離最適化

最終的な選択は、チームの技術レベル、プロジェクトの複雑さ、保守性の要求などを総合的に考慮して決定することが重要です。特に大規模プロジェクトでは、短期的な速度向上だけでなく、長期的な保守性も十分に検討していただければと思います。

関連リンク