github.com の Issue ページのリアルタイム更新の実装ってどうなってるの
いつの日からか(数年前?)、github.com の Issue/PR ページでは新しいコメントがつくとページをリロードせずとも表示されるようになった。あれはどうやって実装されているのか。
github.com は確か Ruby on Rails 製なので素直に Rails の機能で実装するなら Turbo Streams (WebSocket を使うやつ) か、あるいはフロントの JS でポーリングして更新を取得してるとか?
HTML ソースを見ると <turbo-frame> がモリモリに使われてるのがわかってちょっとうれしくなったけど、これは関係ない。ブラウザのインスペクタで通信を覗いてもポーリングしてる様子や WebSocket 通信をしている様子がない🤔
適当な issue ページにコメントを追加して、別タブで開いた同ページにそれが反映された時の通信を覗いてみると、updatable-content-observer.ts
や alive.ts
というファイルのコードがデータ取得を行っているのがわかった。
alive.ts
を見ると SharedWorker がいて、そいつが WebSocket を使ってサーバとやり取りをしていることが窺えた。Worker が通信してたからインスペクタのネットワークタブを見てもリクエストが見えなかったんか〜〜〜
ところでなんでミニファイされた JS じゃなくて元のきれいな TS コードが見えるんだろう。ソースマップも上がってるのかな。
chrome://inspect/#workers
から SharedWorker のコードを見に行ける。
-
SharedWorker 上で動いている
AliveSession
クラスが WebSocket 通信をしてくれてる
-
ブラウザ (not worker) 上で動いている
AliveSessionProxy
クラスが worker から受け取ったデータをCustomEvent
に詰めてdispatchEvent
してる
-
updatable-content-observer.ts
でCustomEvent
をリッスンして、受け取ったデータでupdateContent
を呼んで DOM を更新してる
-
WebSocket から受け取ってるのはコンテンツの
gid
だけっぽくて、更新内容はupdateContent
の時にサーバから fetch してるっぽい
SharedWorker を使った自家製 Turbo Streams という感じでした (知らんけど)
SharedWorker を使っているのは、GitHub のページを複数タブで開いたときに WebSocket のコネクションを共有したいからかな。