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-2g 2000 50
2g 1400 70
3g 270 700
4g 0

値から分かるように、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.

4.3 Effective connection types(wicg.github.io)

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

なので、「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 が付与され、サーバー側で判定することができます。

サムネイル画像
Android Chrome 63 のデータセーバー設定画面オリジナル画像

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

change イベント

§

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

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

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

下記のようにすることで、将来的に現行仕様どおり 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 をオンにし、さらに機内モードへ変更しています。

navigator.connection の値 携帯電話回線(LTE) Wi-Fi 機内モード
type cellular wifi none
effectiveType 4g 4g 4g
downlink 1.75 Mb/s 2.7 Mb/s 10 Mb/s
downlinkMax 100 Mb/s Infinity Mb/s 0 Mb/s
rtt 150 ms 150 ms 0 ms
saveData true true true

脚注