近年、リアルタイム性のあるアプリケーションが急速に需要を伸ばしています。チャットアプリ、ストリーミングサービス、リアルタイムのデータダッシュボードなど、これらのアプリケーションはリアルタイムの双方向通信を必要としています。そこで、今回は Microsoft のクラウドサービスである Azure と、人気のある JavaScript フレームワークである Next.js を組み合わせて、WebSocket を使ったリアルタイム通信の実装方法について紹介します。
WebSocket とは
WebSocket は、HTTP とは異なり、クライアントとサーバー間で一度接続が確立されるとその接続は開放されたままになり、リアルタイムの双方向通信が可能になるプロトコルです。これにより、サーバーからクライントへの "プッシュ" 型通信が可能となり、リアルタイム性の高いアプリケーションの実現に貢献します。
Azure の SignalR Service
Azure では、WebSocket 通信を効率的に行うためのサービスとして SignalR Service を提供しています。SignalR は、WebSocket を含む複数の通信プロトコルをサポートしており、接続管理、メッセージ送信等の一部を自動化し、開発者が主にアプリケーションのロジックに集中できるようにするサービスです。
Next.js とは
Next.js は、React のフレームワークの一つで、サーバーサイドレンダリングや静的サイト生成等、様々なレンダリング方法をサポートしています。また、API ルートを提供しており、API サーバーとしても使用することが可能です。
WebSocket 通信の実装
それでは、実際に Azure の SignalR Service と Next.js を使用して、WebSocket 通信を行うアプリケーションの作成方法を見ていきましょう。今回は、シンプルなチャットアプリケーションの作成を例に説明します。
Azure SignalR Service の設定
まずは、Azure ポータルから SignalR Service を作成します。作成したら、左側のメニューから「Keys」を選択し、表示された接続文字列をメモしておきます。
Next.js アプリケーションの作成
次に、Next.js のアプリケーションを作成します。ターミナルで以下のコマンドを実行します。
npx create-next-app@latest --typescript
その後、必要なパッケージをインストールします。今回は、WebSocket の通信を行うためのパッケージとして @microsoft/signalr
を使用します。
npm install @microsoft/signalr
SignalR の接続設定
SignalR Service への接続を設定するために、Next.js の API ルートを使用します。まず、pages/api/negotiate.ts
を作成し、以下のようにコードを記述します。
// pages/api/negotiate.ts
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
import * as azure from "azure-signalr"
export default async function (
context: Context,
req: HttpRequest
): Promise<void> {
const serviceHubContext = new azure.ServiceHubContext(
process.env.SIGNALR_CONNECTION_STRING,
"chat"
)
const connectionInfo = await serviceHubContext.getConnectionInfo()
context.res.body = connectionInfo
}
このコードでは、SignalR Service との接続情報を取得し、その情報をレスポンスとして返す API ルートを作成しています。
フロントエンドの実装
最後に、フロントエンドのコードを実装します。まず、pages/index.tsx
を開き、以下のようにコードを記述します。
// pages/index.tsx
import { useEffect, useState } from "react"
import * as signalR from "@microsoft/signalr"
export default function Home() {
const [hubConnection, setHubConnection] =
useState<signalR.HubConnection | null>(null)
useEffect(() => {
const createHubConnection = async () => {
const res = await fetch("/api/negotiate")
const data = await res.json()
const connection = new signalR.HubConnectionBuilder()
.withUrl(data.url, { accessTokenFactory: () => data.accessToken })
.build()
try {
await connection.start()
console.log("SignalR Connected.")
} catch (err) {
console.log("Error while establishing connection: ", err)
}
setHubConnection(connection)
}
createHubConnection()
}, [])
// ...
}
このコードでは、ページが読み込まれたときに SignalR Service への接続を行う処理を記述しています。
以上で、Azure と Next.js を使った WebSocket 通信の基本的な部分は完成です。次は、受信したメッセージを画面に表示したり、新たなメッセージを送信する機能など、具体的なアプリケーションのロジックを実装していきましょう。