Metro Bundlerとは:プロジェクトバンドリングと動作原理

著者: IT Sectr 公開日: 2026-07-06 読了時間: 8 分

Metro Bundlerは、Metaが開発したReact Native専用のJavaScriptバンドラーであり、フレームワークのコアに含まれています。React Native 0.76の公式ドキュメント(2025年)によると、MetroはFast Refreshによるインクリメンタルビルドと、プラットフォーム固有の拡張子.native.js、.ios.js、.android.jsを使用したモジュール解決を提供します。Webpackとは異なり、Metroは長期間有効なモジュールグラフキャッシュを使用せず、ファイルが変更されるたびにグラフを再構築するため、開発中に即時のホットリロードを実現します。

重要なポイント

  • Metro Bundler — プラットフォーム固有の拡張子をサポートする公式React Native JavaScriptバンドラー
  • Fast Refresh — コード変更時にコンポーネントの状態を保持したままホットリロード
  • Haste Module System — インクリメンタルビルドのための安定したモジュールIDシステム
  • プラットフォーム拡張子 — .native.js、.ios.js、.android.jsによるプラットフォーム別コード分割
  • Hermesバイトコード — Hermesエンジン向けの直接バイトコードビルドモード

Metro Bundlerとは

Metro Bundlerは、MetaがReact Native向けに開発したオープンソースのJavaScriptバンドラーで、すべてのフレームワークプロジェクトでデフォルトで使用されています。Metroの役割は、プロジェクトのJavaScriptコードを依存関係とともに取得し、デバイス上で実行される1つまたは複数のバンドルにまとめることです。汎用バンドラー(Webpack、Rollup、Parcel)とは異なり、Metroはモバイル開発の特性に最適化されています。最小限のビルド時間、開発中のインクリメンタルアップデート、プラットフォームモジュール(Objective-C、Swift、Java、Kotlinネイティブモジュール)の適切な処理を実現します。MetroはReact Native CLIの一部として提供され、個別のインストールは不要です。React Native 0.72以降、Metroバージョン0.80以上はモジュールの並列トランスパイルをサポートし、マルチコアプロセッサでのビルドを最大40%高速化します。

Metroのアーキテクチャ:Resolver、Transformer、Bundler

Metroのアーキテクチャは、ResolverTransformerBundlerの3つの独立したコンポーネントに分かれています。Resolverはモジュールの検索と解決を担当し、import/require式を読み取り、プラットフォーム拡張子を考慮して対応するファイルを見つけ、絶対パスを返します。Transformerはトランスパイルを実行し、Babelをプリセットとプラグインとともに適用して、JSX、TypeScript、FlowをプレーンなJavaScriptに変換します。Bundlerは最終段階で、Resolverからの依存関係グラフとTransformerからの変換済みファイルを受け取り、それらを1つまたは複数のバンドル(モジュールバンドル)にシリアライズします。3つのステップに分割することで、Metroは各段階の結果をキャッシュできます。1つのファイルのみが変更された場合、ResolverとBundlerは残りのモジュールにキャッシュを使用でき、開発モードでビルド速度が最大10倍向上します。

Resolver:モジュール解決とプラットフォーム認識検索

MetroのResolverは、Node.jsのモジュール解決と部分的に互換性のあるモジュール解決アルゴリズムを実装しています。Node.jsとの主な違いは、プラットフォーム拡張子のサポートです。require(‘./Component’)は、指定された優先順位でComponent.native.js、Component.ios.js、Component.android.jsを検索します。Resolverはまた、モジュールを代替実装にマッピングするためのpackage.jsonフィールド“react-native”をサポートします。これはプラットフォーム固有コードを持つライブラリの標準メカニズムです。ファイルが見つからない場合、Resolverは完全な検索スタックを含むエラーをスローします。

Transformer:Babelとトランスパイル

Metro内部のTransformerは、metro-react-native-babel-presetプリセットとともにBabelを使用します。標準設定には、JSXのReact.createElementへの変換、TypeScriptサポート(型情報の除去)、Flowサポート、最新JavaScript標準(async/await、optional chaining、nullish coalescing)のポリフィルが含まれます。Transformerは並列モードで動作し、各モジュールはワーカープロセスのプールを使用して独立してトランスパイルされます(デフォルトでは、数はCPU数に対応します)。Metro 0.80以降、Granular Transformer Cacheがサポートされています。これは個別ファイルレベルでのキャッシュ無効化を実現します。

Metroのプラットフォーム固有拡張子

Metroの重要な機能の1つは、プラットフォームファイル拡張子のサポートです。React Nativeプロジェクトには、同じモジュールの3つのバージョンを含めることができます:Component.ios.js(iOS)、Component.android.js(Android)、Component.native.js(両プラットフォーム)。require(‘./Component’)をインポートする際、Resolverはターゲットビルドプラットフォームに応じて自動的に正しいバージョンを選択します。これにより、条件付きのPlatform.OS構文を使用せずにプラットフォーム依存のコードを記述できます。優先順位は、name.platform.js > name.native.js > name.jsです。.native.js拡張子は、両方のプラットフォームで動作するがウェブとは互換性のない共通コードに使用されます。.ios.jsと.android.js拡張子は、ナビゲーション、ジェスチャー、ファイルシステム操作などの特定機能の実装に使用されます。Metroはresolver.sourceExts設定を通じてカスタム拡張子をサポートします。

js
// metro.config.js — sourceExtsとwatchFoldersの設定
const config = {
  resolver: {
    sourceExts: ['jsx', 'js', 'tsx', 'ts', 'json'],
    platformExtensions: ['ios', 'android', 'native'],
  },
  transformer: {
    babelTransformerPath: require('metro-react-native-babel-transformer'),
  },
  watchFolders: [path.resolve('../shared')],
};

MetroのホットリロードとFast Refresh

Fast Refreshは、Metro上に構築されたReact Nativeのホットリロードメカニズムです。開発者がファイルを変更すると、Metroは変更されたモジュールのみを再トランスパイルし、WebSocketを介してアプリに更新を送信します。Fast Refreshはアプリケーション全体をリロードせずにUIを更新し、JSXまたはスタイルのみが変更された場合はReactコンポーネントの状態を保持します。フックや状態を含むコードが変更された場合、Fast Refreshは変更されたコンポーネントのみを再マウントします。Metroは2つのモードをサポートしています。Hot Module Replacement(HMR)はモジュールのリアルタイム置換、Live Reloadはネイティブモジュールや設定の変更時のアプリケーション全体のリロードです。Fast RefreshはReact Native 0.76でデフォルトで有効になっており、追加設定は不要です。npx react-native startを実行するだけです。

モード速度状態保持トリガー
Fast Refresh200-500msはいJS/TSファイル変更
HMR100-300msはいCSS/スタイル変更
Live Reload1-3sいいえネイティブ設定変更
Full Rebuild10-60sいいえpodspec/build.gradle変更

Metroの設定:metro.config.js

metro.config.jsファイルは、React Nativeプロジェクトのルートに配置されるMetroの設定ファイルです。ここでは、resolver(sourceExts、platformExtensions、extraNodeModules)、transformer(babelTransformerPath、minifierConfig)、server(port、host、enableFastRefresh)、watcher(watchFolders、healthCheck)を設定します。標準のMetro設定は、@react-native/metro-configパッケージ(React Native 0.76+)から継承されます。モノレポプロジェクトの場合は、watchFoldersを追加します。これにより、Metroはプロジェクトルート外のパッケージの変更を追跡できます。sourceExtsを設定するには、カスタムトランスフォーマー用に‘svg’‘png’‘gql’を追加します。Metroはasync関数による非同期設定をサポートしており、環境に基づいた動的な設定生成に役立ちます。

設定によるビルド最適化

Metroビルドの最適化は、適切なキャッシュ設定から始まります。maxWorkersをCPU数マイナス1に設定します。配布ビルドでは、CIでresetCacheを使用します。sourceExtsを最小限に抑えます。余分な拡張子はモジュール解決を遅くします。大規模プロジェクトでは、watchFoldersを必要なディレクトリのみに設定します。MetroはHermesバイトコードの圧縮をサポートしており、標準のTerserよりも小さいバンドルサイズを実現します。minifierPath: ‘metro-minify-terser’を使用してください。

Hermesバンドリング:バイトコードビルド

Metroは、JavaScript AST段階をスキップして直接Hermesバイトコードにビルドするモードをサポートしています。HermesTransformerを使用してビルドすると、モジュールはプレーンJavaScriptではなくHBC(Hermes ByteCode)にコンパイルされます。これにより、バンドルサイズの縮小(30-40%)、アプリケーション起動の高速化(20-30%)、メモリ消費の低減が実現します。有効にするには、metro.config.jsでhermesCommandを設定し、build.gradle(Android)またはPodfile(iOS)でHermesフラグを有効にします。Hermesバンドルのビルドは2段階で行われます。最初にMetroがJavaScriptバンドルをビルドし、次にHermes CLIがそれをHBCに変換します。React Native 0.70以降、HermesはAndroidのデフォルトエンジンですが、iOSでは明示的な有効化が必要です。

Metro vs Webpack:アプローチの比較

MetroWebpackの違いは、それぞれ異なる目的に起因します。Webpackは、プラグインとローダーの大規模なエコシステムを備えたウェブ向けの汎用バンドラーです。MetroはReact Native向けの特殊なバンドラーであり、インクリメンタルビルドの速度とネイティブモジュールの適切な処理を重視しています。Webpackはスマートなキャッシュ無効化を備えた長期間有効なモジュールグラフを使用し、ウェブ上で高速な再ビルドを実現しますが、プラットフォーム拡張子で問題が発生します。Metroはビルド間でグラフをキャッシュせず、毎回構築します。これにより、プラットフォーム拡張子とHasteモジュールの処理が簡素化されます。Webpackはチャンクを使用した動的インポートをサポートし、MetroもReact.lazy()とSuspenseを通じてサポートしますが、アクティブなリクエストは1つに制限されます。Metroのエコシステムは大幅に小さく、style-loader、css-loader、file-loaderの代替はなく、これらのタスクはReact Nativeで別の方法で解決されます。

Metroを選ぶべき場合

MetroはReact Nativeプロジェクトにとって唯一の正しい選択肢です。Webpackはプラットフォーム認識解決をデフォルトでサポートしておらず、WebpackでReact Nativeをセットアップするにはかなりの労力が必要です(haul bundler、expo web packager)。MetroはReact Native CLIに統合され、Metaの公式チームによってサポートされ、React Nativeのリリースごとにアップデートを受け取ります。React Native Webプロジェクトでは、モバイルバンドルにMetroを使用しながら、ウェブビルドにはWebpackを使用できます。

よくある質問

Metro Bundlerのキャッシュをクリアするには?

npx react-native start --reset-cacheを実行するか、プロジェクトルートから$TMPDIR/metro-*フォルダと.metro-health-check*ディレクトリを削除します。代替方法:npx react-native clean — このコマンドは、BabelキャッシュやHasteマップを含むすべてのMetro一時ファイルをクリアします。クリア後、最初のビルドはフルビルド(60〜120秒)になりますが、以降のインクリメンタルビルドは通常の速度に戻ります。

Metroがnode_modulesのモジュールを認識しないのはなぜ?

確認してください:パッケージがpackage.jsonのdependencies(devDependenciesではない)に含まれていることを確認します。モジュールがモノレポ内にある場合は、metro.config.jsのwatchFoldersにパスを追加します。Metroはデフォルトでシンボリックリンクを追跡しません。明示的なマッピングにはresolver.extraNodeModulesを使用します。Yarn PnMの場合は、resolver.useWatchman: falseを設定します。モジュールがプラットフォーム拡張子を使用する場合、指定されたパスに.ios.jsまたは.android.jsファイルが存在することを確認してください。

大規模プロジェクトでMetroビルドを高速化するには?

metro.config.jsのmaxWorkersをCPU数マイナス1に増やしますwatchFoldersは必要なディレクトリのみに設定します。本番ビルドにはHermesバイトコードを使用します。JSの圧縮をスキップして最終ビルドを高速化します。開発時はFast Refreshを有効にします(デフォルトで有効)。sourceExtsは必要な拡張子のみに制限します。レイジーローディングを使用してバンドルをチャンクに分割することを検討してください。

Metroをウェブプロジェクトに使用できますか?

技術的には可能ですが、推奨されません。Metroはウェブビルド向けに最適化されていません。CSS、HTML、画像をモジュールとしてサポートしておらず、ブラウザレベルでの動的インポートによるコード分割もありません。ウェブにはWebpack、Vite、Parcelを使用してください。MetroはReact Native向けの特殊なソリューションであり、ウェブに適応させようとすると、パフォーマンスの低下とローダーエコシステムの欠如を招きます。

MetroとRe.Packの違いは?

Re.Packは、React NativeプロジェクトでMetroをWebpackに置き換えるためのコミュニティツールです。Webpackローダーのエコシステム(css-loader、svg-loader)と高度なコード分割へのアクセスを提供します。ただし、Re.Packは設定がより複雑で、Metaによって公式サポートされておらず、新しいバージョンのReact Nativeとの互換性を保証しません。Metroは唯一公式サポートされているバンドラーであり、安定性とすべてのリリースとの互換性を保証します。

まとめ

  • Metro Bundler — Resolver-Transformer-Bundlerアーキテクチャを備えた公式React Native JavaScriptバンドラー
  • プラットフォーム拡張子(.ios.js、.android.js、.native.js)— プラットフォーム別コード分割のための主要機能
  • Fast Refresh — コンポーネント状態を保持するホットリロード、WebSocket経由で動作
  • 設定 — metro.config.jsによるsourceExts、watchFolders、maxWorkersのビルド最適化
  • Hermesバイトコード — 高速起動と小さなバンドルサイズのためのバイトコードビルドモード
  • Resolver — Haste Module Systemとプラットフォーム認識解決を使用(Webpackとは非互換)
  • Transformer — ワーカープロセスのプールを使用してBabel経由で並列動作
  • MetroはReact Native CLIの一部として提供され、開始に個別のインストールや設定は不要

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください