私がシステム開発(環境整備)をする上でもっとも重要視しているのが**「デバッグ」**です。
プログラミングを始めたばかりのころはデバッグの重要性を知らず、
エラーやバグの原因が特定できずなんども挫折してしまった経験があります。
ただ、その重要性を知っていても、未経験の言語だったりフレームワークだったりすると設定が意外と難しかったり、ベストプラクティスが決まっておらず案外はまってしまったりするのではないでしょうか。
今回はReact Native
+ Expo
+ Typescript
でのアプリの開発を通して、様々なデバッグ方法を試してみたので設定方法も含めて残しておこうと思います。
今後React Native
を使ってネイティブアプリ開発を始めようと考えている方の一番最初のハードルを取り払う足がかりになれば幸いです。
console.log
javascriptではおなじみコマンドですが、react nativeでもコード内に仕込んでおけば、
アプリを起動しているコンソール上に結果を表示させることが可能です。
開発の初期段階で使う分には手軽に動きを確認できるのでおすすめです。
ただし、console.logを使ったデバッグは消し忘れの可能性があります。
その上、コードを汚すことになりアンチパターンとされているため実際の開発ではあまり好ましくはありません。
vscode / react native tools
vscodeは本当に優れたEditerで、react nativeのデバッグもプラグイン(React Native Tools)を導入すれば、ブレイクポイントの配置とステップ実行が可能になります。
少し導入に苦戦したので、以下に導入方法を説明します。
※ 以下方法はExpoで開発しているのが前提条件となります。
1. vscodeでReact Native Tools
プラグインをインストール
2. プロジェクトにvscodeのデバッグ設定(launch.json
)を追加
ドキュメントには様々な開発パターンの設定が記載されていますが、Expoで開発するのであれば、以下の設定でIOSもAndroidも対応できます。
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to packager",
"cwd": "${workspaceFolder}",
"type": "reactnative",
"request": "attach",
// Expoのデバッグポートにアタッチ
"port": "19001"
}
]
}
3. シュミレータIOS
もしくはAndroid
を起動、デバッグモードをオンにする
シュミレータ上で以下、コマンドを打つことで開発者メニューを開くことができます。
IOSシュミレータ: ctrl + cmd + z
Androidシュミレータ: cmd + m
そのリストの中からDebug Remote JS
をクリックします。
4. vscodeのコードの任意の箇所にブレイクポイントを配置、デバッグ実行
Debug Remote JS
をオンにすると、ブラウザでdebugger-ui(http://localhost:19001/debugger-ui/) が開きますが、デバッグポートに対し一つのデバッガしかアタッチできないため、debugger-uiは閉じておきます。(ブラウザのタブを閉じればOKです)
その上でvscode上で先程launch.json
で作成したデバッガを実行します。
コンソールの画面をDEBUG CONSOLE
にすることで、デバッガがアタッチされたか確認することができます。
5. シュミレータを操作し、ブレイクポイントの変数の値を確認
デバッガを実行している状態でシュミレータを操作すると、ブレイクポイントのコードに処理が走ったとき、そこで処理が一時停止します。
その状態で、以下の操作を行うことができます。
- 変数にカーソルをあてると、変数の内容を確認できる
- DEBUG CONSOLEで変数の内容を確認したり、さらに処理を一時的を加えることができる
- ステップ実行して変数の変化を確認
- 変数をwatchリストに加えて、意図通りに変数が変化するか確認
私が良く活用するのは上記ですが、他にも便利機能があるので、できることの詳細は公式サイトを見たほうがわかりやすいです。
https://code.visualstudio.com/docs/editor/debugging#_debug-actions
react native debugger
react native debugger
は別途アプリをインストールする必要がありますが、「UIのデバック」と「Reduxのデバッグ」を同じアプリ内で行うことができます。
Hooks
のおかげでRedux
の存在感は若干薄まりましたが、それでもなお導入しているプロダクトは多いのではないでしょうか。
react native debugger
ダウンロード
以下、リリースページから自分のOSにあうものをダウンロードできます。
※ MacであればHomebrewコマンドを打つだけでダウンロードできます。
brew update && brew cask install react-native-debugger
react native debugger
初期設定
ダウンロードしたアプリを開き、メニューバー → Debugger → Open Config Fileをクリックします。
.rndebuggerrc
ファイルが開くので、デフォルトデバッグポートを以下に書き換えます。
// RNDebugger will open debugger window with the ports when app launched
- defaultRNPackagerPorts: [8080],
+ defaultRNPackagerPorts: [19001],
これで、Expoのデバッガにアタッチできます。
上記vscodeにも記述しましたが、デバッグポートには一つのデバッガしか接続できないためdebugger-ui
もしくはReact Native Tools
は閉じておく必要があります。(複数のデバッガを並列実行する方法もあるかもしれませんが、私の調べた限りでは必要に応じて切り替えて使うのが一番簡単かと思います。)
UIデバッグ
シュミレータ上で開発者メニューを開き「Show Element Inspecter」をオンにします。
あとはUIにカーソルを当てると、react native debugger上にUIのstyle・propsなどの状態を確認したり、書き換えたりすることも可能です。リアルタイムで変化を確認できるため大変便利です。
Reduxデバッグ
Reduxのデバッグを行うためには、まずプロダクトコードのstoreファイルに__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
の記述をおこないます。
公式サイトにはシンプルな記述方法が記載されています。
https://github.com/zalmoxisus/redux-devtools-extension#11-basic-store
今回のプロダクトではこのような記述にしています。
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { reducer as reduxFormReducer } from 'redux-form';
import itemReducer from '../reducers/item';
import rootSaga from '../sagas/item';
/* eslint-disable no-underscore-dangle, @typescript-eslint/no-explicit-any */
const composeEnhancers =
process.env.NODE_ENV === 'development' &&
typeof window === 'object' &&
(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose;
/* eslint-enable */
const sagaMiddleWare = createSagaMiddleware();
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleWare));
const store = createStore(
combineReducers({
item: itemReducer,
form: reduxFormReducer,
}),
enhancer,
);
sagaMiddleWare.run(rootSaga);
export type AllState = ReturnType<typeof store.getState>;
export default store;
以下はredux-formの例ですが、Redux Actionの発行、Store Stateの変化まで一画面で確認することができます。
それ以外にもアクション名やpayloadの値も確認することができます。
debugger-ui / chrome dev tools
上記デバッグ手法を使えば、ほぼほぼ開発におけるデバッグは問題ないかと思いますが、debugger-ui
とChrome dev tools
を使ったデバッグも可能です。
ただし、この手法は以下の理由から、今回の開発では使いませんでした。
- Expoの公式Debuggingドキュメント「Source maps and async functions」内でchrome dev tools内の
source map
と非同期関数は100%信用できないとの記述があること。(であれば、vscodeでステップ実行したほうが良い?) -
Typescript
とWebpack
の設定の影響か、うまくsource map
がうまく生成されなかった
Typescript・Webpackなどの設定を見直せばうまくデバッグできるようになるかもしれませんが、Expoを利用した開発では「vscode」と「react native debugger」で十分デバッグ機能は果たしていると考え、今回はあまり深く追求せず進めることにしました。
もし、このデバッグ手法にメリットを発見する、もしくはもっと簡単にデバッグができる方法を見つけたら記事を更新したいと思います。