JavaScript で navigator.connection を使ってネットワーク情報を取得する

公開日:

修正日:

Network Information API(wicg.github.io)のブラウザ対応度合いが進んでいたのでまとめてみます。先にソースコードを見たい方はCodePen のデモ(codepen.io)をどうぞ。

この API はネットワークの接続情報を取得できるもので、 navigator.connection でアクセスします。読み取り専用のプロパティは

  • type
  • effectiveType
  • downlink
  • downlinkMax
  • rtt
  • saveData

の6つあり、その他にイベントハンドラーとして onchange が存在します。

type

ネットワーク接続のタイプを示します。 Android Chrome などの対応ブラウザで以下にアクセスすると、接続タイプによって "wifi"(Wi-Fi接続時) や "cellular"(LTE接続時など) などが返ってきます。すべての値のリストは仕様の4.1 Underlying connection technology(wicg.github.io)を参照ください。

<script>
console.log(navigator.connection.type);
</script>

例えば動画配信において、この値によって画質を切り替えるといった活用方法が考えられますが、注意したいのはあくまで接続タイプの判定でしかないことで、たとえ Wi-Fi だからといって高速回線とは限らないことです。

effectiveType

先の type は接続の種類、例えば従量課金の可能性があるかどうかといった判定に使えますが、一方で回線の速度を判定基準にしたいケースも多いと思います。そんなときはこちらの effectiveType を使うことで、実効速度を取得することができます。

取得できる値は以下の4種類。

取得値最小RTT(ms)最大ダウンロード速度(Kbps)
slow-2g200050
2g140070
3g270700
4g0

値から分かるように、2017年時点の一般的な状況から設定されたもののようです。仕様書にも

The absolute values provided above are based on real user measurement on Chrome on Android, as captured in April 2017. The user agent MAY update these values in the future to reflect changes in the measurement data.

と、将来的に値が追加・変更される可能性が記されています。

なので、「3G(相当)以上の回線速度だったら」という条件で

if (navigator.connection.effectiveType === '3g' || navigator.connection.effectiveType === '4g')

という記述をしてしまうと、将来的に 5G など更なる大容量回線が出現したときに意図とは異なる挙動になってしまう可能性が考えられるので、そういう場合は downlink, rtt など数値で取得できるプロパティの方を利用した方がいいのかもしれませんね。

downlink, downlinkMax, rtt

それぞれ有効帯域幅の推定値(Mb/s)、その上限値(Mb/s)、RTT値(ミリ秒)を示します。詳細な定義は仕様を参照ください(手抜き)。

なお、 downlinkMax は Infinity (無限大)が返ってくる可能性があります。

saveData

ユーザーがブラウザの設定でデータ使用量の削減モードを有効にしているかどうかを true / false で返すものです。

Chrome にはデータセーバー機能(support.google.com)があり(iOS版を除く)、デスクトップ版は拡張機能「データセーバー」(chrome.google.com)をインストール、 Android 版は「設定」→「データセーバー」をオンにすることで有効化されます。するとHTTPリクエストヘッダーに Save-Data: on が付与され、サーバー側で判定することができます。

図拡大
図1:Android Chrome 63 のデータセーバー設定画面

Chrome 65 からは navigator.connection.saveData が実装されたため[1]、この情報を JavaScript からも使用することができます。

change イベント

接続情報が変更されたときに change イベントが発火します。

navigator.connection.addEventListener('change', () => {
  /* 接続情報が変更されたときの処理 */
});

ただし、 Android版 Firefox 56 は change ではなく typechange イベントを認識し、 Chrome や Android版 Edge は change と typechange を両方認識します。

下記のようにすることで、将来的に現行仕様どおり change のみを認識するブラウザが出現しても問題ないようにすることができます。

const connectionInfo = navigator.connection;
if ('onchange' in connectionInfo) {
  connectionInfo.addEventListener('change', () => {
    /* 接続情報が変更されたときの処理 */
  });
} else if ('ontypechange' in connectionInfo) {
  connectionInfo.addEventListener('typechange', () => {
    /* 接続情報が変更されたときの処理(Android版 Firefox 向け) */
  });
}

デモ

navigator.connection 対応ブラウザで閲覧してください。

以下に Android Chrome Dev 65 (データセーバー機能を有効にした状態)でアクセスした結果を置いておきます。テストは電波が充分に届く場所でスマートフォンを携帯電話回線に繋いだ状態から、 Wi-Fi をオンにし、さらに機内モードへ変更しています。

携帯電話回線(LTE)

typecellular
effectiveType4g
downlink1.75 Mb/s
downlinkMax100 Mb/s
rtt150 ms
saveDatatrue

Wi-Fi

typewifi
effectiveType4g
downlink2.7 Mb/s
downlinkMaxInfinity Mb/s
rtt150 ms
saveDatatrue

機内モード

typenone
effectiveType4g
downlink10 Mb/s
downlinkMax0 Mb/s
rtt0 ms
saveDatatrue