Opóźnienia interakcji (FID/INP)
Naprawa problemów z First Input Delay i Interaction to Next Paint
Czym są FID i INP?
FID (First Input Delay) mierzy czas od momentu pierwszej interakcji użytkownika (kliknięcie, naciśnięcie klawisza) do momentu, gdy przeglądarka zacznie przetwarzać tę interakcję.
INP (Interaction to Next Paint) to nowa metryka, która zastąpi FID w 2024 roku. Mierzy opóźnienie dla wszystkich interakcji użytkownika, nie tylko pierwszej.
Najczęstsze przyczyny opóźnień
1. Długotrwałe zadania JavaScript
Skrypty wykonujące się dłużej niż 50ms blokują główny wątek, powodując opóźnienia w interakcjach.
- Niewydajne pętle i algorytmy
- Przetwarzanie dużych ilości danych
- Synchronous operations
- Brak code splitting
2. Render-blocking JavaScript
Skrypty ładowane synchronicznie w <head> blokują renderowanie i opóźniają interakcje.
3. Zbyt wiele event listeners
Event listeners bez debounce/throttle mogą powodować nadmierne przetwarzanie podczas interakcji.
Naprawa
1. Użyj Web Workers
Przenieś ciężkie obliczenia do Web Worker:
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeData });
worker.onmessage = (e) => {
// Wynik z worker
};
// worker.js
self.onmessage = (e) => {
const result = heavyComputation(e.data.data);
self.postMessage(result);
};2. Code Splitting
Dziel kod na mniejsze chunk'i ładowane na żądanie:
// Dynamic import
const module = await import('./heavy-module.js');
// React lazy loading
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));3. Defer/Async dla JavaScript
<script defer src="app.js"></script> <script async src="analytics.js"></script>
4. Debounce i Throttle
// Debounce - wykonaj po zakończeniu akcji
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}
// Throttle - wykonaj maksymalnie raz na X ms
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}5. requestIdleCallback
Wykonuj niekrytyczne zadania gdy przeglądarka jest bezczynna:
requestIdleCallback(() => {
// Niepilne zadania
processNonCriticalData();
});Checklista optymalizacji
JavaScript
- Minifikuj i kompresuj JavaScript
- Użyj code splitting
- Usuń nieużywany kod (tree shaking)
- Defer lub async dla niekrytycznych skryptów