優れたソフトウェア開発者は、コードをデバッグする方法を知っています。
実際、ほとんどのソフトウェア開発者は新しいコードを書くことよりも、既存のコードをデバッグすることがほとんどです。ネイティブアプリの開発に関しては、開発中のデバッグとエラーの追跡は手間のかかる面倒な作業として有名です。
そこで今回は、React Nativeアプリケーションをデバッグし、実際にエラーを追跡する方法をご紹介していきます。
また、React Native Debuggerというツールを使ったエラー追跡についても触れていきたいと思います。
React Nativeにおけるデバッグの攻略法
開発中のコードを効率的にデバッグするためのデバッグ手法を知っておくと便利です。場合によっては、専用のデバッグツールを使用する方が効率的かもしれません。
まず、React Nativeアプリでコードをデバッグするために使用できる一般的なテクニックをご紹介します。
今回の記事を通して使用する、新しいExpoベースのReact Nativeプロジェクトを作成しました。次のコマンドを実行すると作成できます。
ここでは、簡単なReact Nativeのコードを紹介します。
これはボタンをレンダリングして関数を起動し、コンソールに文字列を表示する簡単なアプリケーションです。
デバッグ用端末を使う
新しいExpoプロジェクトを起動したり、React Nativeアプリを実行したりすると、開発モード中に操作した全てのログがターミナルに表示されます。
これは、expo startコマンドを実行する別のターミナルでも、IDEに統合されたターミナルでもかまいません。
例えば、VS Codeを使用した場合、ターミナルにはアプリで行ったすべてのログが表示されます。
これは、ローカルでアプリケーションを実行する方法と似ています。
ReactやReact Nativeなどのフレームワークを使ったクライアントサイドの開発では、このターミナルでクライアントサイドのログを取得し、開発モードのアプリのデバッグに利用でき、どんな操作をしたときにどんなエラーが起きたのか手軽に確認できます。
さて、それではわざと構文エラーを起こしてみましょう。
上記のセクションのレイアウト定義において、最後にセミコロンを追加してみます。するとターミナルには、このようなエラーが表示されます。
何のファイルで、どんなエラーが、どこの行で起きたのか……エラーメッセージとともに表示されていますね。
Expoターミナルは、すべてのログが最初に表示される場所です。
そのため、アプリをデバッグしているときはいつでも、そのターミナルを最初に見ることができます。
エキスポデバッガー
Expo を React Native で使用する場合、ビルトイン(備え付け)のデバッガーを入手することができます。
このデバッガーは、エラーメッセージを表示し、エラーが表示されたコードの部分を明示し、コード内のエラー部分をマークしてくれます。
React Nativeプロジェクトを物理デバイスで実行している場合、アプリのコードを実行しているExpoアプリでエラーがどのように表示されるかは次のとおりです。
エラーを確認し、コードを簡単にデバッグすることができますが、この場合、スタックトレースはあまり役に立ちません。なぜなら、エミュレータでExpoを使っているのであれば、ログの方が綺麗に整形されているためです。
スタックトレースはありませんが、こちらの方が簡潔で必要な情報だけが表示されていますね。これで混乱を減らし、より早くエラーにたどり着くことができます。
ブラウザで見るReact開発ツール
先ほどはネイティブアプリでした。
続いては、Web上でフロントエンドアプリケーションをデバッグしてみましょう。
ブラウザを開くだけで、コンソールのログやエラー、レンダリングされたUI要素、関連するスタックトレースなど、あらゆるものが表示されます。
ありがたいことに、React NativeやExpoベースのプロジェクトでも同じことができます。React Developer Tools Chrome拡張をインストールするか、次のコマンドを使用してシステムにグローバルインストールするだけで導入可能です。
Expoアプリの端末で、「w」を押せばWeb上でアプリが開きます。
エラー情報が表示され、Webアプリと同じようにデバッグすることができます。
これは、先ほどデバッグターミナルで見たのと同じエラーで、Expoアプリとエミュレーター上でも同じですね。
エラーを修正してアプリのボタンをクリックし、コンソールが何を表示するか見てみましょう。
ここでは、すべてのコンポーネントを表示し、それらを検査し、スタイルを確認し、React NativeアプリのUIをWebアプリのようにデバッグすることができます。
これだけでなく、コンポーネントの状態やProp、レンダリングされた子要素なども見ることができます。
React Nativeアプリで、階層ツリー内のさまざまなコンポーネント間の相互作用など、より複雑なことをデバッグする際に本領発揮します。
React Nativeのデバッガを使う
ここまでで、React Nativeアプリケーションのデバッグに役立つ一般的な方法をいくつか見てきました。
しかし、専用デバッグツールが便利で、コードをよりよくデバッグするのに役立つことがよくあります。
そのようなツールの1つがReact Native Debuggerです。このツールは、組み込みのUIインスペクター、専用のReduxデバッガー、ネットワークリクエストをデバッグするための「ネットワークインスペクター」など、追加のデバッグ機能を搭載しています。
React Native Debuggerのインストールとダウンロード
React Native Debuggerをインストールまたはダウンロードするための公式ガイドをご確認ください。
お使いのOSとシステム設定にしたがってインストールしてください。
このチュートリアルでは、Mac OS M1にReact Native Debuggerをインストールしてダウンロードし、iOSエミュレータ上で実行する方法をご紹介します。
ターミナルで、以下のコマンドを実行します。
macOSのHomebrewパッケージマネージャーを更新しつつ、react-native-debuggerもインストールします。コマンドが正常に実行されると、React Native Debuggerのアイコンが表示されます。
それでは、React Native Debuggerを開いてみましょう。
Expo アプリに React Native デバッガーを接続する
React Native Debuggerがインストールされたので、Expoアプリに接続します。
デフォルトでは、React Native Debuggerはポート8001で実行されますが、これはExpoアプリのポートとは異なる可能性があります。
まず、Expoアプリが独自のデバッガを実行していないことを確認します。次に、Command + Tを押すと新しいReact Nativeデバッガーウィンドウが開きます。
Expoアプリはポート19000で動作しているので、このポートを追加して確認ボタンを押します。
次に、Expo iOSエミュレータにアクセスして、デバイスを振るか、^ + Command + Zを押して、アプリをリモートでデバッグするためのメニューを開きます。
そうすると、ExpoアプリがReact Native Debuggerにリモートで接続されます。
これで、すべてのコンソールログがデバッガのコンソールタブに表示されるようになりました。
React NativeのデバッガでUIを検査する
React Native Debuggerは「UIインスペクタ」を搭載しています。
これは、アプリで使用されているレイアウトスタイルや、テンプレートをデバッグするのに大変役立ちます。
そして、デバッガ上でスタイルを直接編集することができます。
例えば、ボタンまたは TouchableOpacity コンポーネントを検査し、その backgroundColor プロパティを crimson から blue に変更します。
アプリのUIを変更する場合は、UIインスペクタを使ってリアルタイムで行うことができます。
これを使えば、逐一スタイリングに関するエラーを直接デバッグしたり、コンポーネントの階層をデバッグしたりすることが可能になります。
コンポーネントの状態やPropのデバッグ
コンポーネントタブでは、任意のコンポーネントの現在の状態やPropをデバッグすることも可能です。ここでは、シンプルなインクリメント・カウンター・アプリのコードを更新してみました。
「コンポーネント」タブを使うことで、Stateがリアルタイムに更新される様子を確認することができました。いちいちログ出力の処理を差し込まなくても確認できるので、とても便利ですよね。
また、デバッガーを使って直接Stateを操作することも可能です。
したがって、このメソッドを使用し、コンポーネントのStateやPropに関連するコンポーネントのUIに関する不要な動作をデバッグすることができます。
React Native Debuggerのその他の機能
また、デバッガーの「ネットワーク」タブに移動するだけで、アプリで操作した全てのネットワークリクエストを確認することができます。
さらに、「パフォーマンス」と「プロファイラー」タブを使って、アプリケーションのパフォーマンスボトルネックを監視・デバッグすることもできます。
エラー追跡
ここまでReact Nativeアプリの開発時のエラーをデバッグする方法について見てきました。
これらのエラーが本番環境で現れない可能性は、限りなくゼロに近いと思われます。
アプリの実行時に発生したエラーを追跡することも重要で、リリース時にこれらのエラーを修正したり、アプリの不要な動作についてユーザーに知らせたりすることができます。
エラー追跡は、欠陥のあるコードをリリースする際にも、大きな効率化につながります。
優れたエラー追跡ツールは、エラーの発生方法、発生時期、発生原因について深い洞察を与えてくれます。
また、アプリとネイティブコンポーネント、不具合のあるプラグイン、破損したパッケージとの相互作用に基づくエラーなど、他のタイプのエラーを検出したり、クラッシュを検出したりするのにも役立ちます。
React Nativeのプラグインの不具合エラーについて
Reactのエコシステム全体は、サードパーティのプラグインや依存関係に大きく依存しています。しかしその分、不具合のあるプラグインエラーが発生するリスクも生じます。
最も典型的なものは、Expo/React Nativeの現在のバージョンでサポートされていないプラグインをインストールしたり、場合によってはネイティブのエコシステムをサポートしないWebプラグインをインストールしたりすることです。
例として、Expoにreact-Facebook-loginプラグインをインストールした場合のfaulty pluginエラーが起きた場合を挙げます。
Expo/React Nativeのバージョンをアップグレードすると、プラグインの不具合エラーも発生することがあります。
これは、プラグインを手動で設定しようとしているときや、内部プラグインが自動的に安定したバージョンに更新されないときに発生することがあります。
例えば、Expo SDK 45にアップグレードして、プラグインreact-native-fbadsを導入しようとすると、次のようなエラーが発生することがあります。
パッケージ “react-native-fbads” には有効なコンフィグプラグインが含まれていません。
さらに、プラグインを明示的にインストールしようとすると、別のエラーに遭遇することがあります。
PluginError: モジュール “react-native-fbads “のプラグインを解決するのに失敗しました。
Sentryによるネイティブレイヤーでのエラー検出について
Sentryは、ネイティブアプリケーションのクラッシュに関連するエラーを追跡し、ダッシュボードにイベントを表示することで、そのエラーに関するより多くの文脈的な情報を提供します。
ユーザーのデバイスでアプリケーションがクラッシュした際、その不具合がどの端末で起きたのか、Sentryは詳細に通知してくれます。
また、正確なスタックトレースとコンソール出力も提供しています。
しかし、Nintendo 64コンソールは修復できません。もしそれが可能だったらどうでしょうか?
マリオ64をロードして、マウンテンデューを割って、隠れた金貨をひとつひとつ取りに戻ることができるのです。楽しい週末になりそうですね!(伝わりますか?)
……真面目な話、SentryのReact Nativeのドキュメントを軽く読んでみることをオススメします。どちらにせよ楽しい週末になること間違いなしです。
結論
開発モードでReact Nativeアプリをデバッグするためのさまざまな方法を学んできました。
React Native Debuggerのような強化されたデバッガーツールを使用することは、非常に便利です。
しかし、デバッグ作業は実務の半分に過ぎません。アプリケーションがユーザーの前でどのように動作するかは予想できないので、発生した本番環境のエラーを追跡する必要があります。
Sentryのような優れたエラー追跡ツールは、これらのエラーについて実用的な深い洞察を与えてくれるので、リリースサイクルの早い段階でエラーを修正するのに役立ちます。是非お試しください。
IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。