NetworkInformation API を使ってレンダリング結果を制御してみる?
ちょっと株式会社フロントエンドエンジニアのn13uです.
MDN Web Docsを見ていたら見つけた「NetworkInformation API」について記事を書いてみます.
NetworkInformation APIとは?
Webブラウザからデバイスが接続しているインターネットの接続状況を取得するためのAPIです. 残念ながらGoogle Chromeのみで採用されており、他主要ブラウザでは未実装の状態です.
仕様の詳細はWICG(Web Incubator Community Group)のドキュメントを読んでください.(非公式ドラフトであることはご認識ください)
取得できる情報
接続しているネットワークの速度や想定される無線通信システムのバージョンを取得したり、推定されるダウンロード速度が取得できます.
取得の仕方
navitor.connection
で上記のプロパティを持つreadonlyなinterface、NetworkInformation
にアクセスできます.
APIが利用できない環境ではnavigator.connection
がundefined
になるというわけです.
サンプルコード(MDN Web Docsから引用)[1]
let type = navigator.connection.effectiveType;
function updateConnectionStatus() {
console.log(
`接続の種類が ${type} から ${navigator.connection.effectiveType} に変化`,
);
type = navigator.connection.effectiveType;
}
navigator.connection.addEventListener("change", updateConnectionStatus);
使い道を考える
WICGの仕様書に書かれているRequirements and usecasesには以下の2つが挙げられています.
- 「1.1 Provide an interface for determining the connection type currently used to communicate with the network. ー ネットワークとの通信に現在使用されている接続タイプを判別するためのインターフェースを提供する」
- 「1.2 Provide a way for scripts to be notified if the connection type changes. ー 接続タイプが変更された場合にスクリプトへ通知する方法を提供する。」
ですが、このusecaseで書かれているconnection.type
はChrome OSのChromiumでしか動かないとされています.
では、どうしましょうか.
今回はconnection.effectiveType
の値を利用して、回線の種別によって表示するコンテンツの切り替えを行なってみます.
要件
-
connection.effectiveType
の取りうる値はslow-2g
|2g
|3g
|4g
です. - このうち
4g
の時のみ、ほぼ4Kサイズの画像をコンテンツとして表示しそれ以外の場合はただのテキストを表示します
NetworkInformation APIを利用して接続情報を取得する
ではやってみます. 今回は必要な部分以外の環境を早めに作りたかったためSvelte-Kit / Cloudflare Pagesを利用しています.
NetworkInformation APIを利用し、connectionを取得.存在していた場合にDOMを表示する仕組みを作ります.svelteのif-blockなどを利用すると大きく以下のように実装可能です.
<script lang="ts">
const connection = window.navigator.connection;
</script>
<div>
{#if connection}
<p>接続の種類: {connection.effectiveType}</p>
<p>ダウンロード速度: {connection.downlink} Mbps</p>
<p>最大ダウンロード速度: {connection.downlinkMax}</p>
<p>ラウンドトリップ時間: {connection.rtt} ms</p>
<p>ユーザーセーブデータステータス: {connection.saveData ? '有効' : '無効'}</p>
{:else}
<p>Connection API はサポートされていません</p>
<p>Google ChromeもしくはChromium系ブラウザを利用してください</p>
{/if}
</div>
これで以下のように表示されます(最低限のスタイルを当てています)
⚠️注意点
今回はブラウザのAPIを利用するため、Svelte-KitなどのSSRフレームワークを利用する際にはレンダリングの制御が必要です. 今回は同じ階層の+page.ts
に以下の記述を加えています.
export const ssr = false;
export const csr = true;
接続環境が悪い時だけ画像を表示させない
次に接続環境が悪い時だけ画像を表示させないようにします. これも同様にsvelteのif blockを使うことで表現できます.
サンプルコード
<script lang="ts">
const connection = window.navigator.connection;
</script>
<div>
{#if connection}
<p>接続の種類: {connection.effectiveType}</p>
<p>ダウンロード速度: {connection.downlink} Mbps</p>
<p>最大ダウンロード速度: {connection.downlinkMax}</p>
<p>ラウンドトリップ時間: {connection.rtt} ms</p>
<p>ユーザーセーブデータステータス: {connection.saveData ? '有効' : '無効'}</p>
<div>
{#if connection.effectiveType === '2g' || connection.effectiveType === 'slow-2g' || connection.effectiveType === '3g'}
<p>接続が遅いため、画像を表示しません</p>
{:else}
<img
src="https://picsum.photos/4096/2304"
width="640"
height="360"
alt="ランダムなサイズの大きい画像"
/>
{/if}
</div>
{:else}
<p>Connection API はサポートされていません</p>
<p>Google ChromeもしくはChromium系ブラウザを利用してください</p>
{/if}
</div>
実際に動いている様子を見てみる
通常の通信状況の場合
Chrome DevToolのNetwork Throttolingで速度制限をかけた場合
デモ環境
こんな感じで今後もWeb API試していこうかと思います.
以下環境にてお試しいただけます.
https://web-api-dev.pages.dev/network-information
ソースコード
Discussion