【テクニカル・上級編】Penpotのマルチプレイヤー編集におけるWebSocket通信の仕組みと、社内プロキシ環境で発生する接続エラーの完全解決策 – UI/UX・デザインツール活用バイブル

Penpotのリアルタイム性を極限まで引き出す:社内プロキシ環境を突破するWebSocket/SSE深層アーキテクチャ

「デザインは共同作業である」――この概念を Penpot はオープンソースという土俵で完璧に体現した。しかし、そのリアルタイム協調編集を支える通信レイヤーは、多くのエンタープライズ環境において「ブラックボックス」として恐れられている。

プロキシの背後で頻発する接続断、あるいはメモリを喰いつぶす接続セッション。これらは単なるネットワーク設定のミスではない。プロトコルスタックの理解不足が引き起こす必然だ。今日は、Penpotの心臓部であるWebSocket/SSE通信を掌握し、いかなる過酷なネットワーク環境下でも「爆速」を維持するための設計思想を伝授する。

—

1. リアルタイム協調のエンジン:なぜPenpotは「切れる」のか

Penpotは、WebSocket (ws://) による双方向通信と、Server-Sent Events (SSE) による状態更新のプッシュを組み合わせることで、ミリ秒単位の同期を実現している。

社内プロキシやNginx等のリバースプロキシで接続が切断される主な原因は以下の3点だ。

1. タイムアウトの乖離: プロキシがアイドル接続と判断してセッションを破棄している(Keep-aliveの不一致)。
2. バッファリング: プロキシがSSEのチャンクを溜め込んでしまい、即時性を殺している。
3. プロトコルアップグレードの拒絶: HTTP/1.1からWebSocketへのアップグレードヘッダーが適切にフォワードされていない。

—

2. Nginxによる「完全透過」プロキシ構成の設計

Penpotをプロダクション運用する際、フロントに立つNginxの設定がすべてを決める。以下の設定は、リアルタイム性を損なわず、かつ堅牢性を担保するための「最適解」だ。

Penpot専用のUpstreamおよびプロキシ設定
upstream penpot_backend {
server penpot-backend:6060;
keepalive 32; # バックエンドとの接続を維持し、ハンドシェイクのオーバーヘッドを排除する
}

server {
# … SSL設定などは適宜 …

location /api/ws {
proxy_pass http://penpot_backend;

# WebSocketプロトコルのハンドシェイクを正しく継承
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “Upgrade”;

# 接続のタイムアウトを極限まで引き延ばす
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

# バッファリングを無効化(リアルタイム性を確保)
proxy_buffering off;
}

location /api/events {
proxy_pass http://penpot_backend;

# SSE用のヘッダー制御
proxy_set_header Connection ”;
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_buffering off;
proxy_cache off;
}
}

—

3. DevOpsハック:CLIによる自動ヘルスチェックと最適化

単に設定を書くだけで満足してはいけない。エンジニアたるもの、システムの状態を常に観測し、閾値を超えた瞬間に再起動や再接続を自動化すべきだ。

PenpotのWebSocket接続が健康であるかを監視するGoの簡易スクリプト(抜粋)を共有する。これをサイドカーとして実行し、接続が安定しない場合にメトリクスを吐き出す仕組みを構築せよ。

// 接続監視・再接続エージェントの断片
func monitorConnection(url string) {
conn, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
log.Fatalf(“接続不可: %v”, err)
}
defer conn.Close()

// 接続維持用のPing/Pongハンドラ
conn.SetPingHandler(func(appData string) error {
return conn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(time.Second))
})

// 接続の遅延を計測してPrometheusへメトリクスを送信するロジックをここに組み込む
}

—

4. パフォーマンス最適化の極意:メモリとネットワークの均衡

Penpotの協調編集は、クライアントサイドのメモリ消費が激しい。以下のハックを適用することで、大規模なデザインファイルでもブラウザを落とさないチューニングが可能だ。

  • レンダリングパイプラインの分離: コンポーネントツリーが巨大化した場合、DOMの更新頻度がボトルネックになる。ブラウザのDevToolsで `Rendering` パネルを確認し、不要なレイアウト再計算が発生していないか監視せよ。
  • アセットの最適化: 外部APIを通じてアセットを注入する場合、`Blob` ではなく `ArrayBuffer` を活用し、メインスレッドをブロックしないWeb Workerでの前処理を推奨する。

—

結びに:ツールを「使わされる」立場から「掌握する」立場へ

Penpotは単なるFigmaの代用品ではない。インフラをコード化し、通信を制御し、協調作業のプロトコルを理解する者にとっては、最強の「デザインOS」になり得るポテンシャルを秘めている。

プロキシの問題で躓いている時間は無駄だ。ネットワークスタックを理解し、Nginxをチューニングし、独自の監視エージェントを構築する。その先にあるのは、遅延のない、流れるような共同設計体験だ。

君たちが設計するのはUIだけではない。UIを届けるための「パイプライン」そのものを設計せよ。それが、真のプロダクトエンジニアの仕事だ。

タイトルとURLをコピーしました