Павел Дадыкин, ROGII
Павел Дадыкин
ROGII
window.navigator.onLine
if (navigator.onLine) {
console.log("online");
} else {
console.log("offline");
}
window.addEventListener('online', () => {/* сеть есть */});
window.addEventListener('offline', () => {/* сети нет */});
window.navigator.connection
| Свойство | Описание |
|---|---|
effectiveType |
Тип соединения: 'slow-2g', '2g', '3g', '4g' |
type |
Тип сети: 'wifi', 'cellular', 'bluetooth', 'ethernet', ... |
downlink |
Оценка скорости в Mbps |
downlinkMax |
Максимально возможная скорость |
rtt |
Round-trip time (RTT) в миллисекундах |
saveData |
Включён ли режим экономии трафика |
img, script, fetch, link, xhr и др.
| Метрика | Формула | Назначение |
|---|---|---|
| TCP Handshake | connectEnd - connectStart |
Время установления TCP-соединения |
| DNS Lookup | domainLookupEnd - domainLookupStart |
Время разрешения DNS-имени |
| Redirect Time | redirectEnd - redirectStart |
Задержка из-за переадресации |
| Request Time | responseStart - requestStart |
Время между отправкой запроса и первым байтом ответа |
| TLS Negotiation | requestStart - secureConnectionStart |
Время на установление HTTPS-соединения |
| Fetch Time | responseEnd - fetchStart |
Общее время загрузки (без редиректов) |
| Метрика | Формула | Назначение |
|---|---|---|
| Service Worker | fetchStart - workerStart |
Задержка на обработку запроса в Service Worker |
| Контент сжат? | decodedBodySize ≠ encodedBodySize |
Проверка наличия сжатия (например, gzip) |
| Использован кэш? | transferSize === 0 |
Загрузка из локального кэша |
| Современный протокол? | nextHopProtocol |
Ожидается: h2 или h3 (HTTP/2/3) |
| Блокирует отрисовку? | renderBlockingStatus |
Указывает, задерживает ли ресурс first paint |
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`${entry.name}, ${entry.startTime}`);
}
});
observer.observe({ type: 'resource' });
| Тип (entryType) | Описание |
|---|---|
resource |
Загрузка ресурсов: img, fetch, script и др. |
navigation |
Полные данные о загрузке страницы (TTFB, redirect, DOM и др.) |
mark |
Пользовательские метки времени (performance.mark()) |
measure |
Промежутки между метками (performance.measure()) |
paint |
Ранние метрики отрисовки: first-paint, first-contentful-paint |
first-input |
Время отклика на первое взаимодействие (FID) |
event |
Задержки обработки событий (например, click, input) |
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
if (lastEntry.initiatorType === 'fetch') {
const size = lastEntry.transferSize;
const duration = lastEntry.duration;
const speed = size / duration;
const isConnectionFast = speed > SLOW_CONNECTION_SPEED;
}
| Скорость | Примерная оценка |
|---|---|
| < 50 КБ/сек. | Очень медленно (пользователь заметит лаги) |
| 50–150 КБ/сек. | Замедленное поведение, страдает UX |
| 150–500 КБ/сек. | Приемлемо для большинства действий |
| > 500 КБ/сек. | Хорошее подключение |
const wsStart = performance.now();
const socket = new WebSocket('wss://...');
socket.addEventListener('open', () => {
const wsConnected = performance.now();
console.log(`Connected in ${wsConnected - wsStart}ms`);
});
PerformanceResourceTiming не раскроет многие поля:
console.log(entry.transferSize); // будет 0
console.log(entry.responseEnd); // тоже 0
Timing-Allow-Origin: https://yourdomain.com
или
Timing-Allow-Origin: *
if (entry.name.startsWith(window.location.origin)) {
// считаем скорость
}
Павел Дадыкин
ROGII
https://meloman4eg.github.io/network-issues-fc-2025/