Реалізація WebTransport для low-latency комунікації на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація WebTransport для low-latency комунікації на сайті
Складна
~5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація WebTransport для low-latency комунікації на сайті

WebTransport — браузерний API поверх HTTP/3 (QUIC), доступний з Chrome 97+, Edge 97+, Firefox 114+. На відміну від WebSocket, працює поверх UDP через QUIC, підтримує кілька незалежних потоків і датаграми без head-of-line blocking. Для задач з вимогою задержки нижче 50 мс — це якісний крок вперед порівняно з WebSocket.

Де WebTransport виграє у WebSocket

WebSocket — це один TCP-потік. Потеря пакета блокує всю чергу (head-of-line blocking). При поганому з'єднанні задержки зростають непропорційно. QUIC розв'язує мультиплексуванням: кожен потік незалежний, потеря пакета в одному не впливає на інші.

Характеристика WebSocket WebTransport
Протокол TCP QUIC (UDP)
Мультиплексування Ні Так (незалежні потоки)
Датаграми (ненадійні) Ні Так
Head-of-line blocking Є Ні (для різних потоків)
Поддержка браузерів Всі Chrome 97+, Firefox 114+, Edge 97+
0-RTT reconnect Ні Так (QUIC session resumption)

Вимоги до сервера

WebTransport потребує HTTP/3. Варіанти:

  • Go: quic-go + webtransport-go
  • Node.js: @fails-components/webtransport (експериментальний)
  • Python: aioquic
  • Cloudflare Workers: нативна підтримка WebTransport
  • nginx/Caddy: поки немає нативної підтримки WebTransport

Мінімальний сервер на Go з webtransport-go:

package main

import (
    "context"
    "crypto/tls"
    "log"
    "net/http"

    "github.com/quic-go/quic-go/http3"
    "github.com/quic-go/webtransport-go"
)

func main() {
    s := webtransport.Server{
        H3: http3.Server{
            Addr:      ":4433",
            TLSConfig: loadTLSConfig(), // TLS обов'язковий
        },
    }

    http.HandleFunc("/wt", func(w http.ResponseWriter, r *http.Request) {
        session, err := s.Upgrade(w, r)
        if err != nil {
            log.Printf("upgrade error: %v", err)
            return
        }
        handleSession(session)
    })

    s.ListenAndServe()
}

func handleSession(session *webtransport.Session) {
    ctx := context.Background()
    for {
        // Приймаємо вхідний двонаправлений потік
        stream, err := session.AcceptStream(ctx)
        if err != nil {
            return
        }
        go handleStream(stream)
    }
}

Клієнт: базове підключення

const transport = new WebTransport('https://your-server:4433/wt');

// Чекаємо готовності
await transport.ready;
console.log('WebTransport connected');

transport.closed.then(() => console.log('Transport closed'));

// Обробка помилок
transport.closed.catch(err => console.error('Transport error:', err));

Двонаправлені потоки

Потоки — надійні упорядковані канали, як кілька незалежних WebSocket в одному з'єднанні:

// Клієнт відкриває потік
const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
const reader = stream.readable.getReader();

// Відправка
const encoder = new TextEncoder();
await writer.write(encoder.encode(JSON.stringify({ type: 'subscribe', channel: 'prices' })));

// Читання відповідей
const decoder = new TextDecoder();
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  const message = JSON.parse(decoder.decode(value));
  handleMessage(message);
}

Сервер може ініціювати потоки в сторону клієнта:

// Клієнт приймає вхідні потоки від сервера
const streamReader = transport.incomingBidirectionalStreams.getReader();
while (true) {
  const { value: stream, done } = await streamReader.read();
  if (done) break;
  processServerStream(stream);
}

Датаграми (ненадійні)

Ненадійні, неупорядковані UDP-like повідомлення. Для позицій гравців, метрик, курсорів — задержка важливіша за гарантію:

// Відправка датаграми
const datagramWriter = transport.datagrams.writable.getWriter();
const encoder = new TextEncoder();

function sendPosition(x, y) {
  const data = encoder.encode(JSON.stringify({ x, y, ts: Date.now() }));
  // Не очікуємо підтвердження, fire-and-forget
  datagramWriter.write(data).catch(() => {}); // потеря пакета — норма
}

// Отримання датаграм
const datagramReader = transport.datagrams.readable.getReader();
const decoder = new TextDecoder();

(async () => {
  while (true) {
    const { value, done } = await datagramReader.read();
    if (done) break;
    const msg = JSON.parse(decoder.decode(value));
    updateRemotePosition(msg);
  }
})();

Однонаправлені потоки

Для потокової відправки даних (логування подій, бінарні дані):

// Клієнт → Сервер: однонаправлений потік
const sendStream = await transport.createUnidirectionalStream();
const writer = sendStream.getWriter();
await writer.write(encodeChunk(data));
await writer.close();

// Сервер → Клієнт: вхідні однонаправлені потоки
const incomingReader = transport.incomingUnidirectionalStreams.getReader();
while (true) {
  const { value: stream, done } = await incomingReader.read();
  if (done) break;
  const reader = stream.getReader();
  // читаємо дані з потоку
}

Реальний кейс: торговий терминал

Біржові котирування вимагають мінімальної задержки. Архітектура з WebTransport:

Біржевий фід (UDP) -> Go-сервер -> WebTransport -> Браузер
  • Датаграми для тиків цін (fire-and-forget, втрата 1–2% допустима)
  • Надійний потік для ордерів та підтверджень
  • Окремий потік для підписок на інструменти

Проблема TLS-сертифікату в розробці

WebTransport вимагає валідний TLS. У dev-середовищі — два варіанти:

1. Chrome флаг для self-signed:

chrome://flags/#allow-insecure-localhost

2. Certificate pinning через serverCertificateHashes:

const transport = new WebTransport('https://localhost:4433/wt', {
  serverCertificateHashes: [{
    algorithm: 'sha-256',
    value: hexToArrayBuffer('YOUR_CERT_SHA256_HASH'),
  }],
});

Сертифікат максимум 14 днів при використанні цього методу — генерується при запуску dev-сервера.

Fallback стратегія

WebTransport не підтримується Safari (станом на початок 2026). Потрібен graceful fallback:

async function createTransport(url) {
  if ('WebTransport' in window) {
    try {
      const wt = new WebTransport(url.replace('wss://', 'https://'));
      await wt.ready;
      return new WebTransportAdapter(wt);
    } catch (e) {
      console.warn('WebTransport failed, falling back to WebSocket');
    }
  }
  return new WebSocketAdapter(url);
}

Адаптер приховує різницю за єдиним інтерфейсом send(data) / on('message', cb).

Терміни

  • Прототип з датаграмами та одним потоком — 2–3 дні
  • Production-сервер на Go з TLS + комплексною обробкою потоків — 1 тиждень
  • Повноцінний клієнт з fallback на WebSocket, моніторингом задержок, reconnect — 2–3 тижні
  • Інтеграція з існуючим real-time додатком (замінити WebSocket) — 3–5 днів при наявності адаптерного шару