📶

NetworkInformation API を使ってレンダリング結果を制御してみる?

2024/12/29に公開

ちょっと株式会社フロントエンドエンジニアのn13uです.
MDN Web Docsを見ていたら見つけた「NetworkInformation API」について記事を書いてみます.

NetworkInformation APIとは?

Webブラウザからデバイスが接続しているインターネットの接続状況を取得するためのAPIです. 残念ながらGoogle Chromeのみで採用されており、他主要ブラウザでは未実装の状態です.

仕様の詳細はWICG(Web Incubator Community Group)のドキュメントを読んでください.(非公式ドラフトであることはご認識ください)
https://wicg.github.io/netinfo/

取得できる情報

接続しているネットワークの速度や想定される無線通信システムのバージョンを取得したり、推定されるダウンロード速度が取得できます.

取得の仕方

navitor.connectionで上記のプロパティを持つreadonlyなinterface、NetworkInformationにアクセスできます.
APIが利用できない環境ではnavigator.connectionundefinedになるというわけです.

サンプルコード(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つが挙げられています.

ですが、この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などを利用すると大きく以下のように実装可能です.

+page.svelte
<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に以下の記述を加えています.

+page.ts
export const ssr = false;
export const csr = true;

接続環境が悪い時だけ画像を表示させない

次に接続環境が悪い時だけ画像を表示させないようにします. これも同様にsvelteのif blockを使うことで表現できます.

サンプルコード

+page.svelte

<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で速度制限をかけた場合
Chrome DevToolのThrottoling機能で速度制限をかけると画像が表示されない

デモ環境

こんな感じで今後もWeb API試していこうかと思います.

以下環境にてお試しいただけます.
https://web-api-dev.pages.dev/network-information
ソースコード

脚注
  1. https://developer.mozilla.org/ja/docs/Web/API/Network_Information_API ↩︎

Discussion