Оптимизация First Input Delay (FID) / Interaction to Next Paint (INP) сайта

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Оптимизация First Input Delay (FID) / Interaction to Next Paint (INP) сайта
Сложная
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Оптимизация FID и INP (отзывчивость интерфейса)

FID (First Input Delay) заменён на INP (Interaction to Next Paint) в марте 2024 года. INP — более строгая метрика: измеряет все взаимодействия за сессию, а не только первое. Цель INP: ≤ 200 мс.

Как работает INP

INP = время от действия пользователя (mousedown, keydown, pointerdown) до следующей отрисовки фрейма браузером.

Задержка складывается из:

  1. Input delay — ожидание пока main thread освободится от текущей задачи
  2. Processing time — время выполнения обработчиков событий
  3. Presentation delay — время до фактической отрисовки (layout, paint, composite)

Диагностика медленных взаимодействий

// Мониторинг всех взаимодействий
new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        if (entry.duration > 200) {
            console.warn(`Slow interaction: ${entry.name}`, {
                duration:          entry.duration,
                processingStart:   entry.processingStart,
                processingEnd:     entry.processingEnd,
                inputDelay:        entry.processingStart - entry.startTime,
                processingTime:    entry.processingEnd - entry.processingStart,
                presentationDelay: entry.startTime + entry.duration - entry.processingEnd,
            });
        }
    }
}).observe({ type: 'event', buffered: true, durationThreshold: 16 });

Chrome DevTools → Performance → запись страницы → фильтр Long Tasks (красная полоса). Любая задача > 50 мс — кандидат на оптимизацию.

Устранение Long Tasks

Разбивка синхронных вычислений:

// До: блокирует main thread на сотни мс
function filterProducts(products, filters) {
    return products.filter(p => matchesFilters(p, filters));
}

// После: yield каждые 50 элементов
async function filterProductsAsync(products, filters) {
    const results = [];
    for (let i = 0; i < products.length; i++) {
        if (matchesFilters(products[i], filters)) {
            results.push(products[i]);
        }
        if (i % 50 === 0 && i > 0) {
            await scheduler.yield(); // Chrome 115+
            // fallback: await new Promise(r => setTimeout(r, 0));
        }
    }
    return results;
}

Web Worker для CPU-интенсивных задач:

// worker.js
self.onmessage = function({ data: { products, filters } }) {
    const results = products.filter(p => matchesFilters(p, filters));
    self.postMessage(results);
};

// main.js
const worker = new Worker('/js/filter-worker.js');
worker.postMessage({ products, filters });
worker.onmessage = ({ data }) => setFilteredProducts(data);

Оптимизация React-компонентов

Проблема: избыточный ре-рендер на каждый keystroke:

// Плохо: фильтрация синхронно на каждый keystroke
function ProductList() {
    const [query, setQuery] = useState('');
    const filtered = products.filter(p =>
        p.name.toLowerCase().includes(query.toLowerCase())
    );

    return <>
        <input onChange={e => setQuery(e.target.value)} />
        <ul>{filtered.map(p => <ProductItem key={p.id} product={p} />)}</ul>
    </>;
}

// Хорошо: поле ввода — срочное обновление, список — отложенное
function ProductList() {
    const [query, setQuery] = useState('');
    const [deferredQuery, setDeferredQuery] = useState('');

    const filtered = useMemo(
        () => products.filter(p => p.name.toLowerCase().includes(deferredQuery.toLowerCase())),
        [deferredQuery]
    );

    function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
        const value = e.target.value;
        setQuery(value); // срочно — поле отзывается мгновенно
        startTransition(() => {
            setDeferredQuery(value); // некритично — список обновится позже
        });
    }

    return <>
        <input value={query} onChange={handleChange} />
        <ul>{filtered.map(p => <ProductItem key={p.id} product={p} />)}</ul>
    </>;
}

Виртуализация длинных списков:

import { useVirtualizer } from '@tanstack/react-virtual';

function VirtualProductList({ products }: { products: Product[] }) {
    const parentRef = useRef<HTMLDivElement>(null);
    const rowVirtualizer = useVirtualizer({
        count: products.length,
        getScrollElement: () => parentRef.current,
        estimateSize: () => 80,
        overscan: 5,
    });

    return (
        <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
            <div style={{ height: rowVirtualizer.getTotalSize() }}>
                {rowVirtualizer.getVirtualItems().map(virtualRow => (
                    <div key={virtualRow.index}
                         style={{ transform: `translateY(${virtualRow.start}px)`, position: 'absolute', width: '100%' }}>
                        <ProductItem product={products[virtualRow.index]} />
                    </div>
                ))}
            </div>
        </div>
    );
}

Оптимизация обработчиков событий

// Throttle для scroll/resize обработчиков
const handleScroll = throttle(() => {
    updateStickyHeader();
}, 16); // ~60fps

window.addEventListener('scroll', handleScroll, { passive: true });

// passive: true — сообщает браузеру что обработчик не вызовет preventDefault
// Позволяет браузеру прокрутку без ожидания JS

Third-party скрипты

Чаты, пиксели, аналитика — частая причина плохого INP. Они выполняются в main thread и блокируют взаимодействия.

<!-- Загрузка после основного контента -->
<script>
window.addEventListener('load', () => {
    setTimeout(() => {
        // Инициализация чата/пикселя
        loadChatWidget();
    }, 3000); // задержка 3 секунды после load
});
</script>

Альтернатива — Partytown (Astro/Next.js): запускает third-party скрипты в Web Worker, полностью освобождая main thread.

Целевые показатели INP

Тип взаимодействия Цель
Клик по кнопке < 100 мс
Ввод в поле поиска < 150 мс
Открытие модального окна < 200 мс
Фильтрация каталога < 200 мс

Срок оптимизации: 3–7 дней, зависит от количества проблемных взаимодействий.