公開したら終わり、ではありません。手元では出ないエラーが、本番では出ます。
- 古いブラウザだけで落ちる
- 通信が遅い環境でだけタイミングがずれる
- 特定のデータでだけ
undefinedを触る
そして利用者は報告してくれません。黙って離脱します。だから機械に見張らせます。
Error Boundaryは「見せる」係、監視は「知らせる」係
Error Boundaryの回で、画面が真っ白にならないようにしました。あれは利用者に見せるための仕組みです。
開発者が知るための仕組みは別に要ります。ちょうどcomponentDidCatchが、その受け渡し口になっています。
componentDidCatch(error, errorInfo) {
// ここが「開発者に知らせる」場所
sendToMonitoring(error, errorInfo.componentStack)
}errorInfo.componentStackにはどの部品の中で起きたかが入っています。ファイル名と行番号だけより、はるかに追いやすい情報です。
自前で最低限を書くならこうなります。
window.addEventListener('error', (event) => {
report({ message: event.message, source: event.filename, line: event.lineno })
})
window.addEventListener('unhandledrejection', (event) => {
report({ message: String(event.reason), kind: 'promise' })
})実務では、この2つに加えてまとめ送り・重複の除去・利用者の操作履歴が要るので、専用のサービスを入れるのが早いです(Sentry・Rollbar・Datadogなど。無料の枠で足りることがほとんどです)。
ソースマップが無いと読めない
本番のJavaScriptはまとめて短くされているので、そのままのエラーはこうなります。
TypeError: Cannot read properties of undefined (reading 'name')
at t (index-BNfh9nLk.js:1:48213)tが何なのか分かりません。これを元のコードに読み戻すのがソースマップです。
export default defineConfig({
build: {
sourcemap: true, // .js.map を書き出す
},
})何を送ってはいけないか
監視ツールは送れるものを何でも送ってしまうので、ここは自分で止めます。
- URLのクエリ(
?token=…・?email=…) - フォームの入力値(監視ツールの「操作の記録」機能に入りがち)
Authorizationヘッダー・Cookie- localStorageの中身
セキュリティの回で「フロントに秘密は置けない」と書きましたが、うっかり外に送ってしまう経路としてはここがいちばん現実的です。多くのサービスに送信前に加工する仕組みがあるので、そこで落とします。
// 送る直前に、危ない情報を消す
beforeSend(event) {
delete event.request?.cookies
return event
}エラー以外に見るもの
同じ仕組みで、壊れてはいないが遅いも拾えます。
| 指標 | 何を見ているか |
|---|---|
| LCP | いちばん大きい要素が出るまでの時間(=体感の表示速度) |
| INP | 押してから反応するまでの時間(=もたつき) |
| CLS | 表示中に要素がずれる量(読んでいる途中で動く不快さ) |
Reactのアプリで効くのは、たいてい大量データの回で扱った内容です——画像のサイズ指定でCLS、入力の間引きでINP、コード分割でLCP。
配信をCloudflare PagesやVercelにしているなら、設定を入れるだけの計測機能が付いていることが多いので、まずそれで足ります。
どこまでやるか
| 状況 | やること |
|---|---|
| 個人の小さいサイト | 監視サービスを無料枠で1つ入れる。それだけで十分 |
| 仕事のサービス | エラー監視+パフォーマンス計測+通知の設計 |
| 社内向けツール | エラー監視だけでよいことが多い |
| 静的なページだけ | 入れなくてよい |
公式ドキュメントも見てみる
developer.mozilla.org外部サイトWindow: unhandledrejection イベント - Web API | MDNMDNのunhandledrejection。Error Boundaryが拾えない「catchし忘れたPromise」を捕まえる、標準の仕組みですこのレッスンのまとめ
- Error Boundaryは見せる係、監視は知らせる係。両方要る
componentDidCatchのerrorInfo.componentStackがどの部品で起きたかを教えてくれる- Error Boundaryはイベントハンドラ・
setTimeout・catchし忘れたPromiseを拾えない - だから
errorとunhandledrejectionも見る - ソースマップが無いと本番のエラーは読めない。ただし配信ファイルには含めない
- クエリ・入力値・トークン・Cookieは送らない。送信前に落とす
- 利用者は内部のIDで識別する(氏名やメールではなく)
- LCP・INP・CLSも同じ仕組みで拾える。対策は大量データの回と同じ
- 通知は絞る。鳴りっぱなしの警報は無いのと同じ
次からは最後の章です。まずはReact 19の新しい書き方から。