Hono Advent Calendar 20249日目の記事です。前回は@Stead08さんによる「HonoとCloudflareのサービスでHeadless CMSを作った」でした。
(この記事は「リアルタイム共同編集を実現できるライブラリLoroを試してみる」の続きです。今回使用するLoroに関してはこちらの記事をご覧ください。)
リアルタイム共同編集を実現できるライブラリLoroを試してみる - mooriii's blogCRDTというデータ構造を用いた共同編集機能を実現するライブラリの新たな選択肢Loroを試してみましたblog.mooriii.com
今日はHonoとCloudflare Durable Objectsを使ってリアルタイムで共同編集できるオンラインホワイトボードを作ってみようと思います。
ホワイトボードはtldrawを使い、共同編集機能の実現にはLoroを使用します。
今回作ったアプリのデモサイトを用意したのでぜひ触ってみてください。(予告なくサイトを閉じる可能性があるのでご了承ください)
ソースコードも公開しています。
GitHub - mr04vv/loro-tldraw-durable-objectsContribute to mr04vv/loro-tldraw-durable-objects development by creating an account on GitHub.github.com
(ちなみに記事のアイコンはホワイトボードをイメージしました)
ローカルにシンプルなWebsocketサーバーを立てる
送ったものをオウム返しするWebsocketサーバーを立ててみます。
はじめにCloudflare Workersのプロジェクトを作成します。
hono
をinstallします。
ドキュメントを参考にsrc/index.ts
を以下に書きかえます。
ここまでで一度devサーバーを立ち上げてwscatコマンドでアクセスしてみましょう。
オウム返しされましたね。
他のクライアントにブロードキャストする
このままでは自分が送ったメッセージしか返ってこないので、他に接続しているクライアントにもメッセージを返せるようにしてみましょう。
Cloudflare Workersはリクエストごとに別のプロセスでサーバーが起動します。そのため接続情報をglobalに持つことができません。
これはDurable Objectsを使うと対処できます。
Cloudflare Durable Objects · Cloudflare Durable Objects docsDurable Objects provide a powerful compute API for coordinating multiple clients or users. Each Durable Object has private, transactional and strongly consistent storage attached.developers.cloudflare.com
Durable Objectsはエッジで動くWorkers上の状態を管理するオブジェクトで、IDが同じであれば同一のオブジェクトにアクセスできます。チャットアプリなどでルームIDに対応したオブジェクトを作成できるので、ルーム内の状態を一元管理できます。
ということでDurable Objectsを作っていきます。
まずは wrangler.toml
に以下を追記します。(Doc
となっているところは任意の名前でOKです。)
続いてDocクラスを作ります。
index.ts
でDocを使うように手を加えます。この時エントリーポイントにDurable Objectsを直接書くか、exportする記述が無いとエラーになるので気をつけてください。
20行目の idFromName()
でroomIdごとに異なるDurableObjectsが生成され、部屋ごとに別々の状態を持つことができます。
ここまで来たら一度devサーバーで確認しましょう。
こんな感じでパスごとに部屋を分けることができました。
Loroを使って状態を管理する
今回はホワイトボードの状態を管理するためにLoroを使用します。
(Loroについては前回の記事をご覧ください)
LoroDocをDurableObjectで管理して、新規接続時に保存された状態を返すように手を加えます。サンプルコードではDurableObjectsのStorage APIを使って永続化しています。
Durable Object Storage · Cloudflare Durable Objects docsThe Durable Object Storage API allows Durable Objects to access transactional and strongly consistent storage. A Durable Object's attached storage is private to its unique instance and cannot be accessed by other objects.developers.cloudflare.com
クライアント側の処理は記述量が多いのでリポジトリを参考にしてください。
loro-tldraw-durable-objects/apps/client at main · mr04vv/loro-tldraw-durable-objectsContribute to mr04vv/loro-tldraw-durable-objects development by creating an account on GitHub.github.com
大まかな処理の流れは以下の画像のような感じです。
毎フレームWebsocketと通信してると大変なことになるので、いい感じにthrottleする工夫が必要です。今回はahook のuseThrottoleFn
を使って、一定間隔で操作を間引きました。
ということで完成したのがこちら。
(一応パスパラメータで部屋を指定できます。)
アクセス数によっては予告なしに止める可能性があるのでご了承ください。
まとめ
今日はHonoとCloudflareのDurableObjectsを使って共同編集できるオンラインホワイトボードを作ってみました。
Websocketでステートフルなアプリケーションが簡単に作れちゃうのでおすすめです。ぜひ触ってみてください。
ではまた次回お会いしましょう。
宣伝
我が家の猫のLGTM画像サイトです。ぜひご自由に使ってください。
Lgtlatte - らてのLGTM画像飼い猫らてのLGTM画像を集めましたlgtlatte.mooriii.com