JavaScriptでオンライン・オフライン状態を検出する方法
アプリは問題なく動作しているように見えますが、セッション中にユーザーが接続を失うと何も機能しなくなります。JavaScriptでオンライン・オフライン状態を検出することで、適切に対応できます。警告バナーを表示したり、ネットワークリクエストを一時停止したり、接続が復旧したときに自動的に再試行したりできます。以下、信頼性の高い実装方法を解説します。
重要なポイント
- ページ読み込み時に
navigator.onLineで接続状態を確認し、online/offlineのwindowイベントでリアルタイムの変化に対応します。 navigator.onLineがtrueを返しても、実際のインターネットアクセスが保証されるわけではありません。デバイスが何らかのネットワークに接続されていることを確認するだけです。- 重要な操作を再開する前に、自社のバックエンドへの軽量な
fetchリクエストで実際の接続性を検証してください。 - 本番環境に対応した堅牢なオフライン処理には、これら3つのアプローチを組み合わせます。
簡潔な答え:navigator.onLineとWindowイベント
ブラウザは、JavaScriptでのオンライン/オフライン検出のために2つのツールを提供しています:
navigator.onLine— いつでも読み取り可能なブール値プロパティonlineとofflineのwindowイベント — 接続状態が変化したときに発火
この2つを組み合わせることで、関心のある2つのシナリオに対応できます。ページ読み込み時の状態確認と、状態変化への対応です。
ページ読み込み時にnavigator.onLineを読み取る
if (navigator.onLine) {
console.log('Browser reports online')
} else {
console.log('Browser reports offline')
}
これは、ページが最初に読み込まれたときの初期UI状態を設定するのに便利です。例えば、ユーザーがすでにオフラインの場合に「同期」ボタンを無効化するなどです。
JavaScriptでOnlineとOfflineイベントをリッスンする
タイマーでnavigator.onLineをポーリングするのは無駄です。代わりに、windowのonlineとofflineイベントを使用します:
window.addEventListener('online', () => {
console.log('Connection restored')
// UIを再有効化し、保留中のリクエストを再試行
})
window.addEventListener('offline', () => {
console.log('Connection lost')
// オフラインバナーを表示し、ネットワークアクションを無効化
})
これらのイベントは、ブラウザがネットワーク状態の変化を検出すると自動的に発火するため、ポーリングのオーバーヘッドなしにアプリが即座に反応します。
実践例:オフラインバナーの表示
両方のアプローチを組み合わせた、最小限で本番環境対応のパターンを以下に示します:
const banner = document.getElementById('offline-banner')
function updateOnlineStatus() {
banner.hidden = navigator.onLine
}
// 初期状態を設定
updateOnlineStatus()
// 変化に対応
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
<div id="offline-banner" hidden>
オフラインです。一部の機能が利用できない可能性があります。
</div>
このパターンは、クリーンでイベント駆動型であり、リスナーが一度だけアタッチされ、同じハンドラー関数を再利用するため、メモリリークを回避します。
navigator.onLineの重大な制限
これは、ほとんどのチュートリアルで十分に説明されていない部分です。navigator.onLineは実際のインターネットアクセスを確認しません。
falseは信頼できます — ブラウザは確実にオフラインです。trueは、デバイスが何らかのネットワーク(ルーター、VPNアダプター、LAN)に接続されていることを意味するだけです。ユーザーがキャプティブポータルの背後にいる可能性や、バックエンドに到達できない可能性があります。
navigator.onLineがtrueを返すことを接続の証明として信頼しないでください。 ユーザーがオフラインかもしれないというヒントとして使用し、接続されていることを確認するためには使用しないでください。
Discover how at OpenReplay.com.
ネットワークリクエストで実際の接続性を検証する
navigator.onLineがtrueを返しても重要な操作が失敗する場合は、自社のバックエンドへの軽量なリクエストで到達可能性を確認します:
async function isReachable() {
try {
const response = await fetch('/health-check', {
method: 'HEAD',
cache: 'no-store',
})
return response.ok
} catch {
return false
}
}
CORS問題を回避するため、サードパーティのURLではなく自社のエンドポイントを使用してください。小さく高速なルートへのHEADリクエストにより、帯域幅への影響を最小限に抑えます。
オプション:Network Information API
接続品質のヒント(単なるオンライン/オフラインではなく)については、navigator.connectionがeffectiveType('4g'、'3g'、'slow-2g')やdownlinkなどのプロパティを公開しています。ブラウザサポートはChromiumベースのブラウザに限定されているため、プログレッシブエンハンスメントとしてのみ扱ってください。
DevToolsでオフライン動作をテストする
Chrome DevToolsを開き、Networkタブ → スロットルドロップダウンをOfflineに設定します。これによりofflineイベントがトリガーされ、navigator.onLineがfalseに設定されるため、マシンを切断せずにUIをテストできます。
まとめ
JavaScriptでのオンライン状態の検出は、3つのことに集約されます。読み込み時にnavigator.onLineを読み取り、変化に対応するためにonline/offlineイベントをリッスンし、重要な操作を再開する前にfetchリクエストで実際の接続性を検証することです。この組み合わせにより、実世界の接続シナリオの大部分をクリーンかつ効率的に処理できます。
よくある質問
いいえ。navigator.onLineがtrueを返すのは、デバイスがルーターやVPNアダプターなどの何らかのネットワークに接続されていることを意味するだけです。実際のインターネットアクセスを保証するものではありません。ユーザーがキャプティブポータルの背後にいる可能性や、サーバーがダウンしている可能性があります。重要な操作には、常に実際のネットワークリクエストで検証してください。
はい。onlineとofflineのwindowイベント、およびnavigator.onLineプロパティは、Chrome、Firefox、Safari、Edgeを含むすべてのモダンブラウザでサポートされています。これらはHTML仕様の一部であり、長年にわたって広くサポートされています。
自社サーバーのヘルスチェックエンドポイントに、HEADリクエストなどの軽量なfetchリクエストを送信します。ブラウザキャッシュをバイパスするためにcache no-storeを使用してください。リクエストが成功しokステータスを返せば、ユーザーは真の接続性を持っています。CORS問題を防ぐため、サードパーティURLへのpingは避けてください。
Network Information APIは、有効な接続タイプやダウンリンク速度などの有用なヒントを提供しますが、ブラウザサポートはChromiumベースのブラウザに限定されています。SafariとFirefoxはサポートしていません。プログレッシブエンハンスメントとして扱い、サポートされていないブラウザには常にフォールバック動作を提供してください。
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.