はじめに
Reactアプリを開発していて、「なんかこの画面、もっさりするな...」と感じたことがある人は多いと思います。
原因はだいたい不要な再レンダリングなんですが、これを特定するのが意外と面倒なんですよね。React DevToolsのProfilerを使えばできるんですが、設定が必要だし、結果を見るのもちょっと分かりづらい。Why Did You Render?というライブラリもあるけど、セットアップに手間がかかる。
そんな中で登場したのがReact Scanです。コード変更なしで、Reactアプリのパフォーマンス問題を視覚的に検出できるツールなんですが、これが意外と使いやすくて、個人的にはパフォーマンスデバッグの定番になりつつあります。
GitHubのスター数は20,000を超えていて、注目度もかなり高いですね。
React Scanの特徴
コード変更なしで即座に使える
一番のポイントはこれです。npxコマンド一発で、既存のReactアプリをそのまま分析できます。
npx react-scan@latest http://localhost:3000
これだけで、ローカルで動いているReactアプリのパフォーマンス分析が始まります。ライブラリをインストールする必要もないし、コードに何か追加する必要もない。この手軽さは正直かなりありがたいです。
再レンダリングを視覚的にハイライト
React Scanの最大の特徴は、コンポーネントが再レンダリングされるたびにアウトラインで強調表示してくれることです。
画面を操作しながら、どのコンポーネントが何回レンダリングされているかが一目で分かります。「このボタンをクリックしただけで、なんで親コンポーネント全体が再レンダリングされてるんだ...」みたいな問題がすぐに見つかるわけです。
なぜ再レンダリングされたかも分かる
単にハイライトするだけじゃなくて、クリックすると「なぜこのコンポーネントが再レンダリングされたのか」を教えてくれます。
- props が変わったのか
- state が変わったのか
- context が変わったのか
これが分かると、対策も立てやすいですよね。useCallbackやuseMemoを使うべきなのか、コンポーネントの分割を見直すべきなのか、判断材料になります。
インタラクティブなツールバー
画面上にツールバーが表示されて、そこからいろいろな機能にアクセスできます。常にアクセス可能なので、開発中にサッと確認したいときに便利です。
インストール方法
CLIで即座に使う(おすすめ)
一番簡単なのはCLIを使う方法です。
# npm
npx react-scan@latest http://localhost:3000
# pnpm
pnpm dlx react-scan@latest http://localhost:3000
URLには自分のReactアプリが動いているアドレスを指定します。
プロジェクトにインストールする場合
継続的に使いたい場合は、プロジェクトにインストールすることもできます。
# npm
npm install react-scan
# pnpm
pnpm add react-scan
# yarn
yarn add react-scan
そしてアプリのエントリーポイントでインポートします。
// src/index.tsx または src/main.tsx
import { scan } from "react-scan";
if (process.env.NODE_ENV === "development") {
scan({
enabled: true,
});
}
本番環境では無効にしておくのが基本ですね。
スクリプトタグで追加
HTMLに直接追加する方法もあります。
<script src="https://unpkg.com/react-scan/dist/auto.global.js"></script>
チームメンバーに「ちょっとこれ試してみて」と共有したいときなんかに便利です。
基本的な使い方
1. アプリを起動してReact Scanを実行
# ターミナル1: アプリを起動
npm run dev
# ターミナル2: React Scanを実行
npx react-scan@latest http://localhost:3000
ブラウザが自動で開いて、React Scanが有効になった状態でアプリが表示されます。
2. 画面を操作してレンダリングを観察
普通にアプリを操作してみてください。ボタンをクリックしたり、フォームに入力したり、スクロールしたり。
再レンダリングが発生するたびに、該当するコンポーネントがハイライトされます。色の濃さでレンダリング回数も分かるので、「このコンポーネント、やたらレンダリングされてるな」というのがすぐに分かります。
3. 問題のあるコンポーネントを調査
気になるコンポーネントをクリックすると、詳細な情報が表示されます。
- レンダリング回数
- レンダリングにかかった時間
- 再レンダリングのトリガー(props/state/context)
これを見れば、どこを最適化すべきかの判断材料になります。
実践的なユースケース
リストのパフォーマンス問題を特定
よくあるのが、リストの1項目を更新しただけなのに、リスト全体が再レンダリングされるケースです。
// 問題のあるコード
const TodoList = ({ todos, onToggle }) => {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id} onClick={() => onToggle(todo.id)}>
{todo.text}
</li>
))}
</ul>
);
};
React Scanで確認すると、1つのTodoをクリックしたときにリスト全体がハイライトされるのが分かります。
解決策としては、リストアイテムを別コンポーネントに切り出してReact.memoでラップする、というのが定番ですね。
// 改善後
const TodoItem = React.memo(({ todo, onToggle }) => {
return (
<li onClick={() => onToggle(todo.id)}>
{todo.text}
</li>
);
});
const TodoList = ({ todos, onToggle }) => {
return (
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} onToggle={onToggle} />
))}
</ul>
);
};
フォーム入力時の不要なレンダリング
フォームで1文字入力するたびに画面全体が再レンダリングされる、というのもよくある問題です。
React Scanを使うと、入力のたびにどのコンポーネントが再レンダリングされているかが視覚的に分かるので、状態管理の見直しが必要な箇所を特定しやすくなります。
プロファイラー機能でFPS低下を検出
React Scanにはプロファイラー機能もあって、FPSの低下や遅いインタラクションを自動検出してくれます。
- レンダー時間の詳細な内訳
- Reactフックのオーバーヘッド
- ブラウザの描画時間
これらを分離して表示してくれるので、ボトルネックがReact側にあるのかブラウザ側にあるのかも判断できます。
React DevToolsとの違い
正直なところ、React DevToolsのProfilerでも同じようなことはできます。ただ、React Scanのほうが以下の点で使いやすいと感じています。
- 設定不要: すぐに使える
- 視覚的: リアルタイムでハイライトされるので直感的
- 軽量: 必要なときだけ使える
日常的な開発でサッと確認したいときはReact Scan、本格的なパフォーマンスプロファイリングをしたいときはReact DevTools、という使い分けが個人的にはしっくりきています。
まとめ
React Scanは、Reactアプリのパフォーマンス問題を視覚的に検出できるツールです。
おすすめポイント
- コード変更なしで即座に使える
- 再レンダリングを視覚的にハイライト
- なぜ再レンダリングされたかも分かる
- CLIで手軽に実行できる
- MITライセンスで無料
向いているケース
- 「なんかこの画面遅いな」と感じたときのデバッグ
- パフォーマンス改善の効果を確認したいとき
- チームでパフォーマンス問題を共有したいとき
- React DevToolsの設定が面倒なとき
正直なところ、Reactアプリを開発している人なら、一度は試してみる価値があると思います。パフォーマンス問題の原因特定が圧倒的に楽になりますし、npxで即座に使えるので導入のハードルもほぼゼロです。
「なんかもっさりするな」と思ったら、まずReact Scanで確認する。これが30代エンジニアの新しい習慣になりそうですね。
参考リンク