トランスパイルとは、ソースコードをあるプログラミング言語から別の言語に、同じ抽象化レベルで変換することです。マシンコードへのコンパイルとは異なり、トランスパイルは高水準言語間でコードを変換します:TypeScriptからJavaScript、KotlinからJava、DartからJavaScriptなど。Babel Documentationによると、Babelは週間3500万以上のダウンロードと数百のプラグインをサポートする最も人気のあるトランスパイラです。
重要なポイント
トランスパイル(ソース-to-ソースコンパイル)とは、プログラムをあるプログラミング言語から別の言語に変換し、同じ抽象化レベルを維持するプロセスです。トランスパイラは言語Aのソースコードを受け取り、ターゲット環境で実行可能な言語Bの同等のコードを生成します。代表的な例:TypeScriptからJavaScript、SASSからCSS、Haxeから複数のターゲット言語。
トランスパイルがコンパイルと異なる点は、出力コードが高水準のままで人間が読めることです(ただし、その目的ではありません)。コンパイラ(GCC、LLVM、javac)はコードをマシンコードまたはバイトコードに変換します — これは読めない形式です。トランスパイラは、さらにコンパイルまたは最小化できるコードを生成します。
なぜトランスパイルが必要か。主な理由は互換性です。開発者はモダンな言語(型のあるTypeScript、null safetyのあるKotlin)を使いたいと考えますが、ターゲットプラットフォームがJavaScriptまたはJavaしかサポートしていない場合があります。トランスパイルにより、モダンな言語で記述しながら、ターゲット環境で理解可能なコードをデプロイできます。
| トランスパイラ | ソース → ターゲット | 用途 |
|---|---|---|
| Babel | ES6+/TypeScript → ES5 | Web開発、React、Vue |
| tsc(TypeScript Compiler) | TypeScript → JavaScript | あらゆるTypeScriptアプリケーション |
| kotlinc-js | Kotlin → JavaScript | Kotlin/JS、React Kotlin Wrappers |
| dart2js | Dart → JavaScript | Flutter Web、AngularDart |
| SWC | TypeScript/JS → ES5 | Next.js、Rustベースのバンドル |
抽象化レベルが主な違いです。トランスパイラは同じレベルの言語間(高水準→高水準)でコードを変換します。コンパイラは高水準から低水準(マシンコード、バイトコード)に変換します。LLVM IRは中間表現ですが、それでも元のC++やRustよりも低水準です。
結果の可読性が2つ目の違いです。トランスパイルの結果(TypeScriptからのJavaScript)は読める形式で、ブラウザでデバッグできます。コンパイルの結果(C++からのマシンコード)は読むことを目的としておらず、分析には逆アセンブラが必要です。ソースマップは、トランスパイルされたコードを元のソースにリンクしてデバッグを支援します。
CI/CDパイプラインでは、トランスパイルはビルド段階で実行されます。TypeScriptプロジェクトの場合、tscまたはBabelがDockerコンテナ内で実行され、JavaScriptとソースマップを生成し、その後最小化されてサーバーまたはアプリストアにデプロイされます。トランスパイル結果のキャッシュ設定は重要です — tsc --incrementalは実行間の依存関係グラフを保存し、ビルド時間を30〜50%短縮します。
モバイルプロジェクト(React Native)の場合、Metro Bundlerを介したトランスパイルは、リリースごとにCIサーバーで実行されます。キャッシュディレクトリ(tmp/metro-cache)と--workersによる並列ビルドがプロセスを高速化します。GitHub ActionsとGitLab CIは、実行間でのnode_modulesと.cacheディレクトリのキャッシュをサポートしており、パイプライン時間の短縮に重要です。
実行速度も異なります。マシンコードへのコンパイルは最大のパフォーマンスを提供します。トランスパイルは抽象化レベルのオーバーヘッドを保持します:TypeScriptからのJavaScriptは通常のJavaScriptと同じ速度で実行されます。最適化(TypeScript —strict)は実行時ではなく分析段階で機能します。
シナリオ1:TypeScript → JavaScript — 最も一般的なシナリオです。開発者は型付きのTypeScriptで記述し、tscコンパイラまたはBabelが型アノテーションを削除して純粋なJavaScriptを生成します。すべてのAngularプロジェクトとほとんどのReactプロジェクト(2026年)はTypeScriptトランスパイルを使用しています。State of JS 2025によると、調査対象の開発者の79%が主要プロジェクトでTypeScriptを使用しています。
シナリオ2:Kotlin → JavaScript — フルスタック開発のためにKotlin/JSで使用されます。KotlinコードはIR(Intermediate Representation)を使用してKotlin Compilerを介してJavaScriptにコンパイルされます。Kotlin/JSは外部JSライブラリとの統合のためのTypeScript型付き宣言(.d.ts)をサポートしています。JetBrainsは自社製品のWebインターフェースにKotlin/JSを使用しています。
シナリオ3:SASS/SCSS → CSS — CSSプリプロセッサのトランスパイルです。Dart Sass(推奨実装)は.scssを.cssにトランスパイルし、ミックスイン、変数、ネストされたルール、関数を展開します。これはコンパイルではなく(CSSはCSSのまま)、構文拡張を伴うトランスパイルです。
| パラメータ | トランスパイル | コンパイル | インタプリタ |
|---|---|---|---|
| 入力 → 出力 | 高水準 → 高水準 | 高水準 → マシンコード | コード → 実行時実行 |
| 例 | TypeScript → JavaScript | C++ → ARM/x86 | Python → CPythonランタイム |
| 出力コードが読める | はい | いいえ | 該当なし |
| パフォーマンス | ターゲット言語と同じ | 最大 | コンパイルより低い |
| ランタイムが必要 | いいえ(純粋なターゲットコード) | いいえ | はい |
Babelは最も人気のあるJavaScriptトランスパイラであり、ES6+/ESNextコードをES5互換のJavaScriptに変換します。Babelはプラグインとプリセットのシステムで動作します:各プラグインが1つの変換(アロー関数、async/await、オプショナルチェイニング)を担当します。@babel/preset-envはターゲットブラウザ(browserslist)に基づいて必要なプラグインを自動的に決定します。
Babelのアーキテクチャは3つの段階で構成されています:パース → 変換 → 生成。パーサー(Babylon/@babel/parser)はソースコードをAST(抽象構文木)に変換します。トランスフォーマー(プラグイン)がASTを変更します。ジェネレーター(@babel/generator)が変更されたASTから出力コードを生成します。
// 元のES6+コード
const greet = (name = "World") => {
return `Hello, ${name}!`;
};
class User {
constructor(name) {
this.name = name;
}
}
const data = { user: { address: { city: "Moscow" } } };
const city = data?.user?.address?.city;// Babel後(target: > 0.25%, not dead)
"use strict";
var greet = function (name) {
if (name === void 0) { name = "World"; }
return "Hello, " + name + "!";
};
var User = function (name) {
this.name = name;
};
var data = { user: { address: { city: "Moscow" } } };
var city = data != null
? data.user != null
? data.user.address != null
? data.user.address.city
: void 0
: void 0
: void 0;Babelは次の変換を行いました:アロー関数をfunction式に、デフォルトパラメータ(name = “World”)をvoid 0チェックに、テンプレート文字列を連結に、クラスをコンストラクタ関数に、オプショナルチェイニング(?.)を三項演算子の連鎖に。constはES5互換性のためにvarに置き換えられました。
TypeScriptは厳密に型付けされた言語で、JavaScriptにトランスパイルされます。tscコンパイラ(TypeScript Compiler)は2つのタスクを実行します:型チェックとトランスパイル(出力)。重要なのは、型チェックとトランスパイルは独立した段階であることです。型チェックなしでトランスパイルを実行したり(--noEmitOnError false)、コード生成なしで型チェックを実行したりできます(--noEmit true)。
TypeScriptのトランスパイルは、すべての型アノテーション、インターフェース、型エイリアス、ジェネリックパラメータを削除します — これらはJavaScriptには存在しません。Enumはオブジェクトに、デコレータは関数呼び出しに、async/awaitはジェネレーターに(targetがES2017未満の場合)変換されます。tsconfig.jsonはtarget(JavaScriptバージョン)、module(モジュールシステム)、strict(型チェックの厳格さ)、outDir(出力フォルダ)を制御します。
{
"compilerOptions": {
"target": "es2015",
"module": "esnext",
"lib": ["es2015", "dom"],
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true,
"sourceMap": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}target: “es2015”はtscにES6構文(アロー関数、クラス、let/const)でJavaScriptを生成するよう指示します。module: “esnext”はWebpackでの後続のTree ShakingのためにESモジュール(import/export)を保持します。strict: trueはすべての型チェック(strictNullChecks、noImplicitAny、strictFunctionTypes)を有効にします。declaration: trueはライブラリのTypeScriptコンシューマ向けに.d.tsファイルを生成します。
React NativeはBabelとMetroを使用して、JavaScript/TypeScriptをJavaScriptCore(iOS)またはHermes(Android)で実行可能なコードにトランスパイルします。BabelプラグインはJSX変換、Flow/TypeScriptアノテーション、React Native固有の最適化を追加します。Metro Bundlerはさらにモジュールをバンドルし、開発用のHot Module Replacementを実行します。
FlutterはDartトランスパイルを使用します。Flutter Webの場合、dart2jsはDartを最適化されたJavaScriptにトランスパイルします。Flutter Mobileの場合、dart2nativeはDartをネイティブARMコードにコンパイルします。Flutterは開発用にDart DevCompiler(dartdevc)もサポートしています — これはDartをより速くJavaScriptにトランスパイルしますが、最適化は少なくなります。
// babel.config.js — React Native トランスパイル
module.exports = {
presets: [
["module:metro-react-native-babel-preset"],
],
plugins: [
["module-resolver", {
root: ["."],
alias: {
"@": "./src",
"@components": "./src/components",
},
}],
"react-native-reanimated/plugin",
],
env: {
production: {
plugins: ["transform-remove-console"],
},
},
};metro-react-native-babel-presetには、React Nativeに必要なすべてのプラグインが含まれています:JSX、Flow/TypeScript、Metroモジュールシステム、async/await、クラスプロパティ、デコレータ。module-resolverプラグインは短いインポートのためのエイリアスを追加します(@/components/Buttonを../../components/Buttonの代わりに)。本番モードでは、transform-remove-consoleがコードからすべてのconsole.logを削除します。
よくある質問
トランスパイルはコードを同じレベルの別の言語に変換します(例:TypeScript → JavaScript)。コンパイルは高水準から低水準(C++ → マシンコード)に変換します。トランスパイルの結果は読めますが、コンパイルの結果は読めません。
React Nativeはデフォルトでトランスパイルが必要です — Metro BundlerはBabelを使用して、JSX、TypeScript、モダンJavaScriptをJavaScriptCoreとHermes互換のコードに変換します。Babelなしでは、React NativeはコンポーネントのJSX構文を実行できません。
可能です:Babelと@babel/preset-typescript、SWCはTypeScriptのトランスパイルをサポートしています。tscよりも高速ですが、Babelは型チェックを実行せず、型アノテーションのみを削除します。型チェックのためには、tsc --noEmitを別途実行するか、fork-ts-checker-webpack-pluginを使用する必要があります。
ソースマップは、トランスパイルされたコードを元のソースにリンクするファイルです。ブラウザでのTypeScriptのデバッグを可能にします:ブレークポイントは.tsファイルに設定され、スタックトレースは.jsではなく.tsの行を表示します。ソースマップなしでは、トランスパイルされたコードのデバッグは事実上不可能です。
トランスパイル自体はアプリケーションのパフォーマンスに影響しません — 出力コードはターゲット言語でネイティブに記述されたコードと同じ速度で実行されます。オーバーヘッドが発生するのは、トランスパイラが最適でないコードを生成する場合のみです(例えば、Babelが配列メソッドに大きなポリフィルを作成する場合など)。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。