Web開発ジュニア必見!Chrome DevToolsを組み合わせてバグを効率的に見つける方法
はじめに
Web開発を進める上で、バグやエラーは避けて通れない課題です。特に開発経験がまだ少ない時期は、「なぜか思った通りに動かない」「エラーメッセージの意味が分からない」「どこから調べれば良いのか分からない」といった状況に直面し、デバッグに多くの時間を費やしてしまうことも少なくありません。
デバッグを効率的に行うためには、使用するツールを理解し、状況に応じて適切に使い分けることが重要です。そして、さらに一歩進んで、複数のデバッグツールを組み合わせて活用できるようになると、バグの原因特定までのスピードを格段に向上させることができます。
本記事では、Web開発で広く使われているブラウザのデバッグツール、特にChrome DevToolsに焦点を当て、Console、Sources、Elements、Networkといった主要なタブを連携させて使うことで、どのようにバグを効率的に見つけることができるのかを、具体的なシナリオを通して解説します。
なぜデバッグには複数ツールの連携が必要なのか
Webアプリケーションは、単一の技術だけで構成されているわけではありません。HTMLで構造を定義し、CSSで見た目を整え、JavaScriptで動的な振る舞いを加え、サーバーとのデータ通信を行います。バグやエラーは、これらのいずれかの層、あるいは複数の層が相互に影響し合うことで発生することが多々あります。
例えば、JavaScriptコードにエラーがあっても、それが最終的に画面表示がおかしいという形で現れるかもしれません。あるいは、サーバーからの応答データが不正なために、JavaScriptでそのデータを処理する際にエラーが発生し、結果としてDOMが正しく更新されない、といったケースも考えられます。
このような複雑な問題の原因を特定するためには、単一のツールで一部の情報を見るだけでは不十分な場合があります。
- Console: JavaScriptの実行時エラーや警告、自分で仕込んだログ出力を確認するのに役立ちます。しかし、コードの実行順序や変数の状態を詳細に追跡するには限界があります。
- Sources: JavaScriptコードの実行を一時停止させ(ブレークポイント)、コードを一行ずつ実行したり、変数の値を調べたり、コールスタックを確認したりするのに最適です。しかし、DOMやネットワークの状態は直接見ることはできません。
- Elements: 現在のDOM構造や各要素に適用されているCSSスタイルを確認・変更できます。HTML構造や見た目の問題特定に強いですが、JavaScriptの実行フローやネットワーク通信は関与しません。
- Network: Webページが読み込まれる際に発生する全てのHTTPリクエストとレスポンスの詳細を確認できます。API通信やリソースのロードに関する問題特定に役立ちますが、JavaScriptの実行内容やDOMの状態とは直接的な関係はありません。
このように、それぞれのツールには得意な領域があります。バグの原因を迅速に特定するためには、発生している現象を手がかりに、これらのツールを横断的に、かつ連携させて情報を集めることが効果的です。
実践シナリオ1:JavaScriptエラーで画面表示がおかしい場合
ユーザーのアクション(ボタンクリックなど)をトリガーに、JavaScriptがDOMを操作して画面表示を更新する機能があるとします。しかし、クリックしても何も変化せず、意図した表示になりません。このような場合のデバッグ手順を、Chrome DevToolsの複数タブを連携させて進めてみましょう。
-
最初のステップ:Consoleタブの確認
- まずはChrome DevToolsを開き、Consoleタブにエラーメッセージや警告が出ていないか確認します。
- もしエラーが表示されていれば、そのメッセージを注意深く読みます。特に、エラーの種類(例:
TypeError
,ReferenceError
など)と、エラーが発生したファイル名、行番号、列番号に注目します。 - エラーメッセージ自体が原因の手がかりとなります。「〇〇 is not a function」なら関数呼び出しの問題、「〇〇 is not defined」なら変数や関数が未定義、といった具合です。
javascript // 例:Consoleに表示されるTypeError // Uncaught TypeError: undefined is not a function // at updateDisplay (script.js:25:10) // at HTMLButtonElement.onClick (index.html:40:5)
-
Sourcesタブでのコード実行の追跡
- Consoleでエラーが発生したファイルと行番号が特定できたら、Sourcesタブに切り替えます。
- 画面左側のファイルナビゲーターで該当のJavaScriptファイルを見つけ、クリックして開きます。
- エラーが発生した行、またはその少し手前の行にブレークポイントを設定します。行番号の左側のエリアをクリックするとブレークポイントを設定できます。
- 改めて画面上で、バグを再現する操作(例:ボタンクリック)を行います。
- コードの実行がブレークポイントで一時停止したら、Sourcesタブの右側にあるパネル(Debuggerパネル)を確認します。
- Scope: 現在のスコープにある変数や引数の値を確認できます。
Local
,Closure
,Global
などを展開して、想定通りの値が入っているか調べます。Consoleでエラーメッセージに出ている「undefined」がどの変数に対応するかなどが分かる場合があります。 - Call Stack: 現在の関数がどのように呼び出されたかの履歴を確認できます。どのイベントハンドラから始まり、どの関数を経て現在の場所にたどり着いたのかが分かります。Consoleのエラーメッセージの下に表示されるコールスタックと対応しています。
- Scope: 現在のスコープにある変数や引数の値を確認できます。
- Sourcesタブ上部の実行制御ボタン(Resume, Step Over, Step Into, Step Out)を使って、コードを一行ずつ実行し、変数の値がどのように変化していくか、どの条件分岐を通るかなどを詳細に追跡します。
-
ElementsタブでのDOM状態の確認
- JavaScriptコードが期待通りに実行されているように見えても、画面表示がおかしい場合は、ElementsタブでDOMの状態を確認します。
- JavaScriptによって操作されるべきDOM要素が正しく存在するか、期待通りの属性(
class
,id
,style
など)が適用されているかを確認します。 - Elementsタブの右側にあるStylesパネルで、その要素に適用されているCSSルールを確認します。JavaScriptでクラスを追加・削除した結果、想定外のスタイルが適用されていないか、あるいは適用されるべきスタイルが打ち消されていないかなどを調べます。
- JavaScriptの実行をSourcesタブで一時停止させた状態でElementsタブを見ることで、その時点でのDOMの状態を確認できます。
このシナリオでの連携:
- まず Console でエラー発生箇所を特定し、コードのどのあたりに問題がありそうか大まかな見当をつけます。
- 次に Sources でコードの実行を止め、エラー発生時の変数の値やコールスタックといった、より詳細な実行コンテキストの情報を取得します。
- 必要に応じて Elements を使い、JavaScriptによるDOM操作が正しく行われたか、見た目に影響を与える要素の状態を確認します。
このように、Consoleで見つけた手がかりをもとにSourcesで実行を深掘りし、結果をElementsで検証するという流れが有効です。
実践シナリオ2:APIからのデータが画面に反映されない場合
WebアプリケーションがバックエンドAPIからデータを取得し、そのデータを使って動的にコンテンツを表示するケースを考えます。ページを開いてもデータが表示されない、あるいは不完全な情報が表示されるといった場合のデバッグ手順です。
-
最初のステップ:Networkタブの確認
- まず、Chrome DevToolsを開き、Networkタブに切り替えます。
- Networkタブを開いた状態でページをリロードするか、APIリクエストが実行される操作を行います。
- 表示されたリクエストリストの中から、目的のAPIへのリクエストを探します。
- リクエストをクリックし、右側に表示される詳細パネルを確認します。
- Headers: リクエスト/レスポンスヘッダーを確認します。特にステータスコード(例: 200 OK, 404 Not Found, 500 Internal Server Errorなど)を確認し、リクエストが成功したか、サーバー側でエラーが発生していないかなどを把握します。
- Preview / Response: APIからの応答データを確認します。データが期待通りの形式(JSONなど)で、必要な情報が全て含まれているかを確認します。データ自体が欠落していたり、想定外の形式だったりしないか調べます。
- Timing: リクエストの各段階にかかった時間を確認できます。特定の段階で異常に時間がかかっている場合、サーバー側の問題やネットワークの遅延が原因かもしれません。
- Networkタブ上部のフィルター機能を使って、XHR/Fetchリクエストのみを表示させたり、特定の文字列を含むURLで絞り込んだりすると目的のリクエストを見つけやすくなります。
-
Sourcesタブでのデータ処理の追跡
- NetworkタブでAPIリクエストが成功し、データも期待通りに返ってきているのに画面表示がおかしい場合、JavaScriptでのデータ処理に問題がある可能性が高いです。
- Sourcesタブに切り替え、APIからの応答データを受け取って処理を開始する箇所の少し手前にブレークポイントを設定します。
- Networkタブで確認した応答データが、JavaScriptコード内でどのように変数に格納され、どのように処理されていくのかを、ブレークポイントとステップ実行で追跡します。
- API応答データの特定のプロパティにアクセスしようとして「undefined」になる、データの配列をループ処理しているがループが実行されない、といった問題を発見できる可能性があります。
-
Consoleタブでのデータの調査と実行
- Sourcesタブで実行を一時停止した状態で、Consoleタブを開きます。
- Consoleでは、Sourcesで一時停止しているスコープ内の変数にアクセスできます。APIから取得したデータが格納されている変数をConsoleで入力し、Enterキーを押すことで、その時点でのデータの正確な内容を確認できます。
- また、Consoleを使って、データを使ってDOMを更新する処理の一部を手動で実行してみることも有効です。例えば、データ処理後の関数呼び出しを手動で実行し、エラーが発生するかどうかを確認できます。
-
Elementsタブでの表示結果の確認
- データ処理コードを追跡し、問題が見つからなかった場合、あるいは処理結果としてDOMが正しく構築されているかを確認するためにElementsタブを使用します。
- APIデータを使って追加されるべきHTML要素がDOMツリー内に存在するか、その要素の内容(テキスト、属性など)が期待通りになっているかを確認します。
- データに基づいて適用されるCSSクラスなどがあり、それがスタイルに影響を与えている場合は、Stylesパネルで確認します。
このシナリオでの連携:
- まず Network で、APIリクエスト自体が正しく行われ、サーバーから期待通りのデータが返ってきているかを確認します。外部との通信に問題がないか最初に切り分けることができます。
- データ受信に問題がなければ、Sources で、受信したデータがJavaScriptコード内でどのように扱われているかを詳細に追跡します。
- Console を利用して、実行停止中の変数内容を確認したり、特定のコード片を試行的に実行したりします。
- 最後に Elements で、データ処理の結果がDOMに正しく反映されているか、見た目の問題がないかを確認します。
効率アップのための追加テクニック
複数のツールを連携させるだけでなく、それぞれのツールが持つ高度な機能も活用することで、さらにデバッグ効率を上げることができます。
- Consoleでのログ出力の活用:
- 単に変数を出力するだけでなく、
console.table()
で配列やオブジェクトを見やすく表示したり、console.group()
でログをグループ化したり、console.time()
/console.timeEnd()
で処理時間を計測したりできます。 - 特定の条件下でのみログを出力したい場合は、if文と組み合わせるのが一般的ですが、Console API自体には条件付きログの機能はありません。代わりにSourcesタブの条件付きブレークポイントを活用しましょう。
- 単に変数を出力するだけでなく、
- Sourcesでの条件付きブレークポイント:
- ブレークポイントを設定する際に、ブレークポイントの行番号を右クリックし、「Edit breakpoint」を選択します。
- 表示された入力フィールドに、ブレークポイントで実行を停止したい条件となるJavaScript式(例:
userId === 10
,data.length === 0
など)を入力します。 - この機能を使うと、特定の条件が満たされたときにだけ実行を停止させることができるため、大量のデータや繰り返しの処理の中で特定のケースをデバッグしたい場合に非常に有効です。
- 条件式の代わりにJavaScriptコードを記述し、そのコードがfalseを返した場合にブレークしない「Logpoint」として使うこともできます(入力フィールドに式ではなく評価されるコードを書き、左端のドロップダウンを「Logpoint」に変更)。これを使うと、コードに
console.log
を埋め込むことなく、DevTools上からログ出力を行うことができます。
- Networkタブでのフィルタリングと検索:
- 多数のリクエストが表示されるNetworkタブでは、上部のフィルターバーを活用しましょう。ファイルタイプ(XHR, JS, CSS, Imgなど)で絞り込んだり、URLの一部やメソッド(GET, POSTなど)、ステータスコード(404, 500など)で検索したりすることで、目的のリクエストを素早く見つけられます。
- Ctrl+F (Cmd+F) で、リクエスト/レスポンスのヘッダーや本文を含む全てを検索することも可能です。
- ショートカットキーの活用:
- DevToolsを開く: F12 または Ctrl+Shift+I (Cmd+Option+I)
- Sourcesタブでの実行制御(F10: Step over, F11: Step into, Shift+F11: Step out, F8: Resume/Pause)は頻繁に使用するため覚えておくと効率が上がります。
まとめ
Web開発におけるデバッグは、単一のツールに頼るのではなく、Chrome DevToolsのConsole, Sources, Elements, Networkといった様々なタブが提供する機能を、発生している問題に応じて組み合わせて活用することが鍵となります。
エラーメッセージの確認から始め、コード実行の追跡、DOMやスタイルの状態確認、そしてネットワーク通信の検証と、多角的な視点から情報を集めることで、バグの根本原因を効率的に特定できるようになります。
今回紹介したシナリオはあくまで一例ですが、これらの基本的な考え方を理解し、ご自身の開発で直面する様々な状況に合わせて応用していくことで、デバッグ能力は確実に向上します。
最初はどのツールをいつ使えば良いか迷うこともあるかもしれませんが、まずはConsoleでエラーがないか確認し、必要に応じてSourcesで実行を追跡する、といった基本的な連携パターンから試してみてください。経験を積むにつれて、バグの性質に応じた最適なツールの組み合わせが自然と身についてくるはずです。
デバッグは開発プロセスの一部であり、避けることはできません。しかし、適切なツールの知識と活用スキルを身につけることで、デバッグにかかる時間を減らし、より効率的に開発を進めることができるようになります。ぜひ本記事を参考に、日々の開発でChrome DevToolsの複数ツール連携を実践してみてください。